home *** CD-ROM | disk | FTP | other *** search
/ The Arsenal Files 1 / The Arsenal Files (Arsenal Computer).ISO / archive / unixarc.pt5 < prev    next >
Internet Message Format  |  1994-01-23  |  67KB

  1. From pacbell!ames!mailrus!cornell!rochester!bbn!bbn.com!rsalz Fri Jul  1 13:13:46 1988
  2. From: rsalz@bbn.com (Rich Salz)
  3. Newsgroups: comp.sources.unix
  4. Subject: v15i081:  ARC (PC compression program), v5.21, Part05/05
  5. Message-ID: <969@fig.bbn.com>
  6. Date: 1 Jul 88 20:13:46 GMT
  7.  
  8. Submitted-by: hyc@math.lsa.umich.edu
  9. Posting-number: Volume 15, Issue 81
  10. Archive-name: arc5.21/part05
  11.  
  12. #--------------------------------CUT HERE-------------------------------------
  13. #! /bin/sh
  14. #
  15. # This is a shell archive.  Save this into a file, edit it
  16. # and delete all lines above this comment.  Then give this
  17. # file to sh by executing the command "sh file".  The files
  18. # will be extracted into the current directory owned by
  19. # you with default permissions.
  20. #
  21. # The files contained herein are:
  22. #
  23. # -rw-r--r--  1 hyc         11514 Jun 13 13:54 arcsqs.c
  24. # -rw-r--r--  1 hyc          4680 Jun 13 00:43 arcsvc.c
  25. # -rw-r--r--  1 hyc          1284 Apr 19 01:40 arctst.c
  26. # -rw-r--r--  1 hyc          5347 Jun 18 03:13 arcunp.c
  27. # -rw-r--r--  1 hyc          2484 Jun  2 16:28 arcusq.c
  28. # -rw-r--r--  1 hyc          9032 Jun 13 13:56 dtime.c
  29. # -rw-r--r--  1 hyc          7327 Apr 11 19:11 dtimep.lex
  30. # -rw-r--r--  1 hyc           356 Apr 11 19:12 lexedit.sed
  31. # -rw-r--r--  1 hyc          3713 Jun 13 13:59 lexstring.c
  32. # -rw-r--r--  1 hyc          2241 Apr 11 19:13 libtws.3
  33. # -rw-r--r--  1 hyc          9053 Jun  6 01:04 marc.c
  34. #
  35. echo 'x - arcsqs.c'
  36. if test -f arcsqs.c; then echo 'shar: not overwriting arcsqs.c'; else
  37. sed 's/^X//' << '________This_Is_The_END________' > arcsqs.c
  38. X/*
  39. X * $Header: arcsqs.c,v 1.2 88/06/01 16:31:39 hyc Locked $
  40. X */
  41. X
  42. X/*  ARC - Archive utility - SQUASH
  43. X(C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
  44. X This is a quick hack to ARCLZW to make it handle squashed archives.
  45. X Dan Lanciani (ddl@harvard.*) July 87
  46. X*/
  47. X
  48. X/*
  49. X * $Header: arcsqs.c,v 1.2 88/06/01 16:31:39 hyc Locked $
  50. X */
  51. X
  52. X#include <stdio.h>
  53. X#include "arc.h"
  54. X
  55. X#if    MSDOS
  56. Xchar    *setmem();
  57. X#else
  58. Xchar    *memset();
  59. X#endif
  60. Xint    getc_unp();
  61. Xvoid    putc_pak(), putc_unp();
  62. Xstatic void    putcode();
  63. X
  64. X/* definitions for the new dynamic Lempel-Zev crunching */
  65. X
  66. X#define BITS   13        /* maximum bits per code */
  67. X#define HSIZE  10007        /* 80% occupancy */
  68. X#define INIT_BITS 9        /* initial number of bits/code */
  69. Xstatic int      n_bits;        /* number of bits/code */
  70. Xstatic int      maxcode;    /* maximum code, given n_bits */
  71. X#define MAXCODE(n)      ((1<<(n)) - 1)    /* maximum code calculation */
  72. Xstatic int      maxcodemax = 1 << BITS;    /* largest possible code (+1) */
  73. X
  74. Xstatic unsigned char buf[BITS];    /* input/output buffer */
  75. X
  76. Xstatic unsigned char lmask[9] =    /* left side masks */
  77. X{0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00};
  78. Xstatic unsigned char rmask[9] =    /* right side masks */
  79. X{0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
  80. X
  81. Xstatic int      offset;        /* byte offset for code output */
  82. Xstatic long     in_count;    /* length of input */
  83. Xstatic long     bytes_out;    /* length of compressed output */
  84. Xstatic unsigned short ent;
  85. X
  86. Xlong     htab[HSIZE];    /* hash code table   (crunch) */
  87. Xunsigned short codetab[HSIZE];    /* string code table (crunch) */
  88. X
  89. Xstatic unsigned short *prefix = codetab;  /* prefix code table (uncrunch) */
  90. Xstatic unsigned char *suffix=(unsigned char *)htab;  /* suffix table (uncrunch) */
  91. Xstatic int      free_ent;    /* first unused entry */
  92. Xstatic int      firstcmp;    /* true at start of compression */
  93. Xunsigned char stack[HSIZE];    /* local push/pop stack */
  94. X
  95. X/*
  96. X * block compression parameters -- after all codes are used up,
  97. X * and compression rate changes, start over.
  98. X */
  99. X
  100. Xstatic int      clear_flg;
  101. Xstatic long     ratio;
  102. X#define CHECK_GAP 10000        /* ratio check interval */
  103. Xstatic long     checkpoint;
  104. X
  105. X/*
  106. X * the next two codes should not be changed lightly, as they must not
  107. X * lie within the contiguous general code space.
  108. X */
  109. X#define FIRST   257        /* first free entry */
  110. X#define CLEAR   256        /* table clear output code */
  111. X
  112. Xstatic void
  113. Xcl_block(t)            /* table clear for block compress */
  114. X    FILE           *t;    /* our output file */
  115. X{
  116. X    long            rat;
  117. X
  118. X    checkpoint = in_count + CHECK_GAP;
  119. X
  120. X    if (in_count > 0x007fffffL) {    /* shift will overflow */
  121. X        rat = bytes_out >> 8;
  122. X        if (rat == 0)    /* Don't divide by zero */
  123. X            rat = 0x7fffffffL;
  124. X        else
  125. X            rat = in_count / rat;
  126. X    } else
  127. X        rat = (in_count << 8) / bytes_out;    /* 8 fractional bits */
  128. X
  129. X    if (rat > ratio)
  130. X        ratio = rat;
  131. X    else {
  132. X        ratio = 0;
  133. X        setmem(htab, HSIZE * sizeof(long), 0xff);
  134. X        free_ent = FIRST;
  135. X        clear_flg = 1;
  136. X        putcode(CLEAR, t);
  137. X    }
  138. X}
  139. X
  140. X/*****************************************************************
  141. X *
  142. X * Output a given code.
  143. X * Inputs:
  144. X *      code:   A n_bits-bit integer.  If == -1, then EOF.  This assumes
  145. X *              that n_bits =< (long)wordsize - 1.
  146. X * Outputs:
  147. X *      Outputs code to the file.
  148. X * Assumptions:
  149. X *      Chars are 8 bits long.
  150. X * Algorithm:
  151. X *      Maintain a BITS character long buffer (so that 8 codes will
  152. X * fit in it exactly).  When the buffer fills up empty it and start over.
  153. X */
  154. X
  155. Xstatic void
  156. Xputcode(code, t)        /* output a code */
  157. X    int             code;    /* code to output */
  158. X    FILE           *t;    /* where to put it */
  159. X{
  160. X    int             r_off = offset;    /* right offset */
  161. X    int             bits = n_bits;    /* bits to go */
  162. X    unsigned char  *bp = buf;    /* buffer pointer */
  163. X    int             n;    /* index */
  164. X    register int    ztmp;
  165. X
  166. X    if (code >= 0) {    /* if a real code *//* Get to the first byte. */
  167. X        bp += (r_off >> 3);
  168. X        r_off &= 7;
  169. X
  170. X        /*
  171. X         * Since code is always >= 8 bits, only need to mask the
  172. X         * first hunk on the left. 
  173. X         */
  174. X        ztmp = (code << r_off) & lmask[r_off];
  175. X        *bp = (*bp & rmask[r_off]) | ztmp;
  176. X        bp++;
  177. X        bits -= (8 - r_off);
  178. X        code >>= (8 - r_off);
  179. X
  180. X        /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
  181. X        if (bits >= 8) {
  182. X            *bp++ = code;
  183. X            code >>= 8;
  184. X            bits -= 8;
  185. X        }
  186. X        /* Last bits. */
  187. X        if (bits)
  188. X            *bp = code;
  189. X
  190. X        offset += n_bits;
  191. X
  192. X        if (offset == (n_bits << 3)) {
  193. X            bp = buf;
  194. X            bits = n_bits;
  195. X            bytes_out += bits;
  196. X            do
  197. X                putc_pak(*bp++, t);
  198. X            while (--bits);
  199. X            offset = 0;
  200. X        }
  201. X        /*
  202. X         * If the next entry is going to be too big for the code
  203. X         * size, then increase it, if possible. 
  204. X         */
  205. X        if (free_ent > maxcode || clear_flg > 0) {    /* Write the whole
  206. X                                 * buffer, because the
  207. X                                 * input side won't
  208. X                                 * discover the size
  209. X                                 * increase until after
  210. X                                 * it has read it. */
  211. X            if (offset > 0) {
  212. X                bp = buf;    /* reset pointer for writing */
  213. X                bytes_out += n = n_bits;
  214. X                while (n--)
  215. X                    putc_pak(*bp++, t);
  216. X            }
  217. X            offset = 0;
  218. X
  219. X            if (clear_flg) {    /* reset if clearing */
  220. X                maxcode = MAXCODE(n_bits = INIT_BITS);
  221. X                clear_flg = 0;
  222. X            } else {/* else use more bits */
  223. X                n_bits++;
  224. X                if (n_bits == BITS)
  225. X                    maxcode = maxcodemax;
  226. X                else
  227. X                    maxcode = MAXCODE(n_bits);
  228. X            }
  229. X        }
  230. X    } else {        /* dump the buffer on EOF */
  231. X        bytes_out += n = (offset + 7) / 8;
  232. X
  233. X        if (offset > 0)
  234. X            while (n--)
  235. X                putc_pak(*bp++, t);
  236. X        offset = 0;
  237. X    }
  238. X}
  239. X
  240. X/*****************************************************************
  241. X *
  242. X * Read one code from the standard input.  If EOF, return -1.
  243. X * Inputs:
  244. X *      cmpin
  245. X * Outputs:
  246. X *      code or -1 is returned.
  247. X */
  248. X
  249. Xstatic int
  250. Xgetcode(f)            /* get a code */
  251. X    FILE           *f;    /* file to get from */
  252. X{
  253. X    int             code;
  254. X    static int      offset = 0, size = 0;
  255. X    int             r_off, bits;
  256. X    unsigned char  *bp = buf;
  257. X
  258. X    if (clear_flg > 0 || offset >= size || free_ent > maxcode) {
  259. X        /* If the next entry will be too big for the current code
  260. X         * size, then we must increase the size. This implies reading
  261. X         * a new buffer full, too. */
  262. X        if (free_ent > maxcode) {
  263. X            n_bits++;
  264. X            if (n_bits == BITS)
  265. X                maxcode = maxcodemax;    /* won't get any bigger
  266. X                             * now */
  267. X            else
  268. X                maxcode = MAXCODE(n_bits);
  269. X        }
  270. X        if (clear_flg > 0) {
  271. X            maxcode = MAXCODE(n_bits = INIT_BITS);
  272. X            clear_flg = 0;
  273. X        }
  274. X        for (size = 0; size < n_bits; size++) {
  275. X            if ((code = getc_unp(f)) == EOF)
  276. X                break;
  277. X            else
  278. X                buf[size] = code;
  279. X        }
  280. X        if (size <= 0)
  281. X            return -1;    /* end of file */
  282. X
  283. X        offset = 0;
  284. X        /* Round size down to integral number of codes */
  285. X        size = (size << 3) - (n_bits - 1);
  286. X    }
  287. X    r_off = offset;
  288. X    bits = n_bits;
  289. X
  290. X    /*
  291. X     * Get to the first byte. 
  292. X     */
  293. X    bp += (r_off >> 3);
  294. X    r_off &= 7;
  295. X
  296. X    /* Get first part (low order bits) */
  297. X    code = (*bp++ >> r_off);
  298. X    bits -= 8 - r_off;
  299. X    r_off = 8 - r_off;    /* now, offset into code word */
  300. X
  301. X    /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
  302. X    if (bits >= 8) {
  303. X        code |= *bp++ << r_off;
  304. X        r_off += 8;
  305. X        bits -= 8;
  306. X    }
  307. X    /* high order bits. */
  308. X    code |= (*bp & rmask[bits]) << r_off;
  309. X    offset += n_bits;
  310. X
  311. X    return code;
  312. X}
  313. X
  314. X/*
  315. X * compress a file
  316. X *
  317. X * Algorithm:  use open addressing double hashing (no chaining) on the
  318. X * prefix code / next character combination.  We do a variant of Knuth's
  319. X * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
  320. X * secondary probe.  Here, the modular division first probe is gives way
  321. X * to a faster exclusive-or manipulation.  Also do block compression with
  322. X * an adaptive reset, where the code table is cleared when the compression
  323. X * ratio decreases, but after the table fills.  The variable-length output
  324. X * codes are re-sized at this point, and a special CLEAR code is generated
  325. X * for the decompressor.
  326. X */
  327. X
  328. Xvoid
  329. Xsqinit_cm()            /* initialize for compression */
  330. X{
  331. X    offset = 0;
  332. X    bytes_out = 0;
  333. X    clear_flg = 0;
  334. X    ratio = 0;
  335. X    in_count = 1;
  336. X    checkpoint = CHECK_GAP;
  337. X    maxcode = MAXCODE(n_bits = INIT_BITS);
  338. X    free_ent = FIRST;
  339. X    setmem(htab, HSIZE * sizeof(long), 0xff);
  340. X    n_bits = INIT_BITS;    /* set starting code size */
  341. X
  342. X    firstcmp = 1;        /* next byte will be first */
  343. X}
  344. X
  345. Xvoid
  346. Xsqputc_cm(c, t)            /* compress a character */
  347. X    unsigned char   c;    /* character to compress */
  348. X    FILE           *t;    /* where to put it */
  349. X{
  350. X    static long     fcode;
  351. X    static int      hshift;
  352. X    int             i;
  353. X    int             disp;
  354. X
  355. X    if (firstcmp) {        /* special case for first byte */
  356. X        ent = c;    /* remember first byte */
  357. X
  358. X        hshift = 0;
  359. X        for (fcode = (long) HSIZE; fcode < 65536L; fcode *= 2L)
  360. X            hshift++;
  361. X        hshift = 8 - hshift;    /* set hash code range bund */
  362. X
  363. X        firstcmp = 0;    /* no longer first */
  364. X        return;
  365. X    }
  366. X    in_count++;
  367. X    fcode = (long) (((long) c << BITS) + ent);
  368. X    i = (c << hshift) ^ ent;/* xor hashing */
  369. X
  370. X    if (htab[i] == fcode) {
  371. X        ent = codetab[i];
  372. X        return;
  373. X    } else if (htab[i] < 0)    /* empty slot */
  374. X        goto nomatch;
  375. X    disp = HSIZE - i;    /* secondary hash (after G.Knott) */
  376. X    if (i == 0)
  377. X        disp = 1;
  378. X
  379. Xprobe:
  380. X    if ((i -= disp) < 0)
  381. X        i += HSIZE;
  382. X
  383. X    if (htab[i] == fcode) {
  384. X        ent = codetab[i];
  385. X        return;
  386. X    }
  387. X    if (htab[i] > 0)
  388. X        goto probe;
  389. X
  390. Xnomatch:
  391. X    putcode(ent, t);
  392. X    ent = c;
  393. X    if (free_ent < maxcodemax) {
  394. X        codetab[i] = free_ent++;    /* code -> hashtable */
  395. X        htab[i] = fcode;
  396. X    } else if ((long) in_count >= checkpoint)
  397. X        cl_block(t);
  398. X}
  399. X
  400. Xlong 
  401. Xsqpred_cm(t)            /* finish compressing a file */
  402. X    FILE           *t;    /* where to put it */
  403. X{
  404. X    putcode(ent, t);    /* put out the final code */
  405. X    putcode(-1, t);        /* tell output we are done */
  406. X
  407. X    return bytes_out;    /* say how big it got */
  408. X}
  409. X
  410. X/*
  411. X * Decompress a file.  This routine adapts to the codes in the file
  412. X * building the string table on-the-fly; requiring no table to be stored
  413. X * in the compressed file.  The tables used herein are shared with those of
  414. X * the compress() routine.  See the definitions above.
  415. X */
  416. X
  417. Xvoid
  418. Xsqdecomp(f, t)            /* decompress a file */
  419. X    FILE           *f;    /* file to read codes from */
  420. X    FILE           *t;    /* file to write text to */
  421. X{
  422. X    unsigned char  *stackp;
  423. X    int             finchar;
  424. X    int             code, oldcode, incode;
  425. X
  426. X    n_bits = INIT_BITS;    /* set starting code size */
  427. X    clear_flg = 0;
  428. X
  429. X    /*
  430. X     * As above, initialize the first 256 entries in the table. 
  431. X     */
  432. X    maxcode = MAXCODE(n_bits = INIT_BITS);
  433. X    for (code = 255; code >= 0; code--) {
  434. X        prefix[code] = 0;
  435. X        suffix[code] = (unsigned char) code;
  436. X    }
  437. X    free_ent = FIRST;
  438. X
  439. X    finchar = oldcode = getcode(f);
  440. X    if (oldcode == -1)    /* EOF already? */
  441. X        return;        /* Get out of here */
  442. X    putc_unp((char) finchar, t);    /* first code must be 8 bits=char */
  443. X    stackp = stack;
  444. X
  445. X    while ((code = getcode(f)) > -1) {
  446. X        if (code == CLEAR) {
  447. X            for (code = 255; code >= 0; code--)
  448. X                prefix[code] = 0;
  449. X            clear_flg = 1;
  450. X            free_ent = FIRST - 1;
  451. X            if ((code = getcode(f)) == -1)    /* O, untimely death! */
  452. X                break;
  453. X        }
  454. X        incode = code;
  455. X        /*
  456. X         * Special case for KwKwK string. 
  457. X         */
  458. X        if (code >= free_ent) {
  459. X            if (code > free_ent) {
  460. X                if (warn) {
  461. X                    printf("Corrupted compressed file.\n");
  462. X                    printf("Invalid code %d when max is %d.\n",
  463. X                        code, free_ent);
  464. X                }
  465. X                nerrs++;
  466. X                return;
  467. X            }
  468. X            *stackp++ = finchar;
  469. X            code = oldcode;
  470. X        }
  471. X        /*
  472. X         * Generate output characters in reverse order 
  473. X         */
  474. X        while (code >= 256) {
  475. X            *stackp++ = suffix[code];
  476. X            code = prefix[code];
  477. X        }
  478. X        *stackp++ = finchar = suffix[code];
  479. X
  480. X        /*
  481. X         * And put them out in forward order 
  482. X         */
  483. X        do
  484. X            putc_unp(*--stackp, t);
  485. X        while (stackp > stack);
  486. X
  487. X        /*
  488. X         * Generate the new entry. 
  489. X         */
  490. X        if ((code = free_ent) < maxcodemax) {
  491. X            prefix[code] = (unsigned short) oldcode;
  492. X            suffix[code] = finchar;
  493. X            free_ent = code + 1;
  494. X        }
  495. X        /*
  496. X         * Remember previous code. 
  497. X         */
  498. X        oldcode = incode;
  499. X    }
  500. X}
  501. ________This_Is_The_END________
  502. if test `wc -c < arcsqs.c` -ne    11514; then
  503.     echo 'shar: arcsqs.c was damaged during transit (should have been    11514 bytes)'
  504. fi
  505. fi        ; : end of overwriting check
  506. echo 'x - arcsvc.c'
  507. if test -f arcsvc.c; then echo 'shar: not overwriting arcsvc.c'; else
  508. sed 's/^X//' << '________This_Is_The_END________' > arcsvc.c
  509. X/*
  510. X * $Header: arcsvc.c,v 1.8 88/06/13 00:42:59 hyc Locked $
  511. X */
  512. X
  513. X/*  ARC - Archive utility - ARCSVC
  514. X
  515. X    Version 2.23, created on 04/22/87 at 13:10:10
  516. X
  517. X(C) COPYRIGHT 1985-87 by System Enhancement Associates; ALL RIGHTS RESERVED
  518. X
  519. X    By:     Thom Henderson
  520. X
  521. X    Description:
  522. X     This file contains service routines needed to maintain an archive.
  523. X
  524. X    Language:
  525. X     Computer Innovations Optimizing C86
  526. X*/
  527. X#include <stdio.h>
  528. X#include "arc.h"
  529. X#if    MTS
  530. X#include <mts.h>
  531. X#endif
  532. X
  533. Xvoid    abort(), setstamp();
  534. Xint    unlink();
  535. X
  536. Xvoid
  537. Xopenarc(chg)            /* open archive */
  538. X    int             chg;    /* true to open for changes */
  539. X{
  540. X    FILE           *fopen();/* file opener */
  541. X
  542. X    if (!(arc = fopen(arcname, "rb"))) {
  543. X        if (chg) {
  544. X            if (note)
  545. X                printf("Creating new archive: %s\n", arcname);
  546. X        }
  547. X        else
  548. X            abort("Archive not found: %s", arcname);
  549. X    }
  550. X#if    MTS    /* allow reading archives of max MTS record length */
  551. X    else {
  552. X        char *buffer, *malloc();
  553. X        int inlen;
  554. X        struct GDDSECT *region;
  555. X
  556. X        region=gdinfo(arc->_fd);
  557. X        inlen=region->GDINLEN;
  558. X        buffer=malloc(inlen);
  559. X        setbuf(arc, buffer);
  560. X        arc->_bufsiz=inlen;
  561. X    }
  562. X#endif
  563. X    if (chg) {        /* if opening for changes */
  564. X        if (!(new = fopen(newname, "wb")))
  565. X            abort("Cannot create archive copy: %s", newname);
  566. X
  567. X    changing = chg;        /* note if open for changes */
  568. X    }
  569. X}
  570. X
  571. Xvoid
  572. Xclosearc(chg)            /* close an archive */
  573. X    int             chg;    /* true if archive was changed */
  574. X{
  575. X    if (arc) {        /* if we had an initial archive */
  576. X        fclose(arc);
  577. X        if (kludge)    /* kludge to update timestamp */
  578. X#if    !MTS
  579. X            setstamp(arcname, olddate, oldtime);
  580. X#endif
  581. X    }
  582. X    if (chg) {        /* if things have changed */
  583. X        fclose(new);    /* close the new copy */
  584. X        if (arc) {    /* if we had an original archive */
  585. X            if (keepbak) {    /* if a backup is wanted */
  586. X                unlink(bakname);    /* erase any old copies */
  587. X                if (move(arcname, bakname))
  588. X                    abort("Cannot rename %s to %s", arcname, bakname);
  589. X                printf("Keeping backup archive: %s\n", bakname);
  590. X            } else if (unlink(arcname))
  591. X                abort("Cannot delete old archive: %s", arcname);
  592. X        }
  593. X        if (move(newname, arcname))
  594. X            abort("Cannot move %s to %s", newname, arcname);
  595. X#if    !MTS
  596. X        setstamp(arcname, arcdate, arctime);
  597. X#endif
  598. X    }
  599. X}
  600. X
  601. X/*
  602. X * CRC computation logic
  603. X * 
  604. X * The logic for this method of calculating the CRC 16 bit polynomial is taken
  605. X * from an article by David Schwaderer in the April 1985 issue of PC Tech
  606. X * Journal.
  607. X */
  608. X
  609. Xstatic short      crctab[] =    /* CRC lookup table */
  610. X{
  611. X 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
  612. X 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
  613. X 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
  614. X 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
  615. X 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
  616. X 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
  617. X 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
  618. X 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
  619. X 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
  620. X 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
  621. X 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
  622. X 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
  623. X 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
  624. X 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
  625. X 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
  626. X 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
  627. X 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
  628. X 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
  629. X 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
  630. X 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
  631. X 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
  632. X 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
  633. X 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
  634. X 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
  635. X 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
  636. X 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
  637. X 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
  638. X 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
  639. X 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
  640. X 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
  641. X 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
  642. X 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
  643. X};
  644. X
  645. Xint
  646. Xaddcrc(crc, c)            /* update a CRC check */
  647. X    int             crc;    /* running CRC value */
  648. X    unsigned char   c;    /* character to add */
  649. X{
  650. X    return ((crc >> 8) & 0x00ff) ^ crctab[(crc ^ c) & 0x00ff];
  651. X}
  652. ________This_Is_The_END________
  653. if test `wc -c < arcsvc.c` -ne     4680; then
  654.     echo 'shar: arcsvc.c was damaged during transit (should have been     4680 bytes)'
  655. fi
  656. fi        ; : end of overwriting check
  657. echo 'x - arctst.c'
  658. if test -f arctst.c; then echo 'shar: not overwriting arctst.c'; else
  659. sed 's/^X//' << '________This_Is_The_END________' > arctst.c
  660. X/*
  661. X * $Header: arctst.c,v 1.4 88/04/19 01:40:28 hyc Exp $
  662. X */
  663. X
  664. X/*
  665. X * ARC - Archive utility - ARCTST
  666. X * 
  667. X * Version 2.12, created on 02/03/86 at 23:00:40
  668. X * 
  669. X * (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
  670. X * 
  671. X * By:  Thom Henderson
  672. X * 
  673. X * Description: This file contains the routines used to test archive integrity.
  674. X * 
  675. X * Language: Computer Innovations Optimizing C86
  676. X */
  677. X#include <stdio.h>
  678. X#include "arc.h"
  679. X
  680. Xvoid    openarc();
  681. Xint    readhdr(), unpack();
  682. X
  683. Xvoid
  684. Xtstarc()
  685. X{                /* test integrity of an archive */
  686. X    struct heads    hdr;    /* file header */
  687. X    long            arcsize, ftell();    /* archive size */
  688. X
  689. X    openarc(0);        /* open archive for reading */
  690. X    fseek(arc, 0L, 2);    /* move to end of archive */
  691. X    arcsize = ftell(arc);    /* see how big it is */
  692. X    fseek(arc, 0L, 0);    /* return to top of archive */
  693. X
  694. X    while (readhdr(&hdr, arc)) {
  695. X        if (ftell(arc) + hdr.size > arcsize) {
  696. X            printf("Archive truncated in file %s\n", hdr.name);
  697. X            nerrs++;
  698. X            break;
  699. X        } else {
  700. X            printf("Testing file: %-12s  ", hdr.name);
  701. X            fflush(stdout);
  702. X            if (unpack(arc, NULL, &hdr))
  703. X                nerrs++;
  704. X            else
  705. X                printf("okay\n");
  706. X        }
  707. X    }
  708. X
  709. X    if (nerrs < 1)
  710. X        printf("No errors detected\n");
  711. X    else if (nerrs == 1)
  712. X        printf("One error detected\n");
  713. X    else
  714. X        printf("%d errors detected\n", nerrs);
  715. X}
  716. ________This_Is_The_END________
  717. if test `wc -c < arctst.c` -ne     1284; then
  718.     echo 'shar: arctst.c was damaged during transit (should have been     1284 bytes)'
  719. fi
  720. fi        ; : end of overwriting check
  721. echo 'x - arcunp.c'
  722. if test -f arcunp.c; then echo 'shar: not overwriting arcunp.c'; else
  723. sed 's/^X//' << '________This_Is_The_END________' > arcunp.c
  724. X/*
  725. X * $Header: arcunp.c,v 1.7 88/06/18 03:12:36 hyc Locked $
  726. X */
  727. X
  728. X/*
  729. X * ARC - Archive utility - ARCUNP
  730. X * 
  731. X * Version 3.17, created on 02/13/86 at 10:20:08
  732. X * 
  733. X * (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
  734. X * 
  735. X * By:  Thom Henderson
  736. X * 
  737. X * Description: This file contains the routines used to expand a file when
  738. X * taking it out of an archive.
  739. X * 
  740. X * Language: Computer Innovations Optimizing C86
  741. X */
  742. X#include <stdio.h>
  743. X#include "arc.h"
  744. X#if    MTS
  745. X#include <ctype.h>
  746. X#endif
  747. X
  748. Xvoid    setcode(), init_usq(), init_ucr(), decomp(), sqdecomp();
  749. Xvoid    abort(), putc_tst();
  750. Xint    getc_usq(), getc_ucr(), addcrc();
  751. X
  752. X/* stuff for repeat unpacking */
  753. X
  754. X#define DLE 0x90        /* repeat byte flag */
  755. X
  756. Xstatic int      state;        /* repeat unpacking state */
  757. X
  758. X/* repeat unpacking states */
  759. X
  760. X#define NOHIST 0        /* no relevant history */
  761. X#define INREP 1            /* sending a repeated value */
  762. X
  763. Xstatic short    crcval;        /* CRC check value */
  764. Xstatic long     size;        /* bytes to read */
  765. X#if    !DOS
  766. Xstatic int    gotcr;        /* got a carriage return? */
  767. X#endif
  768. X
  769. Xint
  770. Xunpack(f, t, hdr)        /* unpack an archive entry */
  771. X    FILE           *f, *t;    /* source, destination */
  772. X    struct heads   *hdr;    /* pointer to file header data */
  773. X{
  774. X    int             c;    /* one char of stream */
  775. X    void            putc_unp();
  776. X    void            putc_ncr();
  777. X    int             getc_unp();
  778. X
  779. X    /* setups common to all methods */
  780. X#if    !DOS
  781. X    gotcr = 0;
  782. X#endif
  783. X    crcval = 0;        /* reset CRC check value */
  784. X    size = hdr->size;    /* set input byte counter */
  785. X    state = NOHIST;        /* initial repeat unpacking state */
  786. X    setcode();        /* set up for decoding */
  787. X
  788. X    /* use whatever method is appropriate */
  789. X
  790. X    switch (hdrver) {    /* choose proper unpack method */
  791. X    case 1:        /* standard packing */
  792. X    case 2:
  793. X        while ((c = getc_unp(f)) != EOF)
  794. X            putc_unp((char) c, t);
  795. X        break;
  796. X
  797. X    case 3:        /* non-repeat packing */
  798. X        while ((c = getc_unp(f)) != EOF)
  799. X            putc_ncr((unsigned char) c, t);
  800. X        break;
  801. X
  802. X    case 4:        /* Huffman squeezing */
  803. X        init_usq(f);
  804. X        while ((c = getc_usq(f)) != EOF)
  805. X            putc_ncr((unsigned char) c, t);
  806. X        break;
  807. X
  808. X    case 5:        /* Lempel-Zev compression */
  809. X        init_ucr(0);
  810. X        while ((c = getc_ucr(f)) != EOF)
  811. X            putc_unp((char) c, t);
  812. X        break;
  813. X
  814. X    case 6:        /* Lempel-Zev plus non-repeat */
  815. X        init_ucr(0);
  816. X        while ((c = getc_ucr(f)) != EOF)
  817. X            putc_ncr((unsigned char) c, t);
  818. X        break;
  819. X
  820. X    case 7:        /* L-Z plus ncr with new hash */
  821. X        init_ucr(1);
  822. X        while ((c = getc_ucr(f)) != EOF)
  823. X            putc_ncr((unsigned char) c, t);
  824. X        break;
  825. X
  826. X    case 8:        /* dynamic Lempel-Zev */
  827. X        decomp(f, t);
  828. X        break;
  829. X
  830. X    case 9:        /* Squashing */
  831. X        sqdecomp(f, t);
  832. X        break;
  833. X
  834. X    default:        /* unknown method */
  835. X        if (warn) {
  836. X            printf("I don't know how to unpack file %s\n", hdr->name);
  837. X            printf("I think you need a newer version of ARC\n");
  838. X            nerrs++;
  839. X        }
  840. X        fseek(f, hdr->size, 1);    /* skip over bad file */
  841. X        return 1;    /* note defective file */
  842. X    }
  843. X
  844. X    /* cleanups common to all methods */
  845. X
  846. X    if (crcval != hdr->crc) {
  847. X        if (warn || kludge) {
  848. X            printf("WARNING: File %s fails CRC check\n", hdr->name);
  849. X            nerrs++;
  850. X        }
  851. X        return 1;    /* note defective file */
  852. X    }
  853. X    return 0;        /* file is okay */
  854. X}
  855. X
  856. X/*
  857. X * This routine is used to put bytes in the output file.  It also performs
  858. X * various housekeeping functions, such as maintaining the CRC check value.
  859. X */
  860. X
  861. Xvoid
  862. Xputc_unp(c, t)            /* output an unpacked byte */
  863. X    char            c;    /* byte to output */
  864. X    FILE           *t;    /* file to output to */
  865. X{
  866. X    crcval = addcrc(crcval, c);    /* update the CRC check value */
  867. X#if    MTS
  868. X    if (!image)
  869. X        atoe(&c, 1);
  870. X#endif
  871. X#if    DOS
  872. X    putc_tst(c, t);
  873. X#else
  874. X    if (image)
  875. X        putc_tst(c, t);
  876. X    else {
  877. X        if (gotcr) {
  878. X            gotcr = 0;
  879. X            if (c != '\n')
  880. X                putc_tst('\r', t);
  881. X        }
  882. X        if (c == '\r')
  883. X            gotcr = 1;
  884. X        else
  885. X            putc_tst(c, t);
  886. X    }
  887. X#endif
  888. X}
  889. X
  890. X/*
  891. X * This routine is used to decode non-repeat compression.  Bytes are passed
  892. X * one at a time in coded format, and are written out uncoded. The data is
  893. X * stored normally, except that runs of more than two characters are
  894. X * represented as:
  895. X * 
  896. X * <char> <DLE> <count>
  897. X * 
  898. X * With a special case that a count of zero indicates a DLE as data, not as a
  899. X * repeat marker.
  900. X */
  901. X
  902. Xvoid
  903. Xputc_ncr(c, t)            /* put NCR coded bytes */
  904. X    unsigned char   c;    /* next byte of stream */
  905. X    FILE           *t;    /* file to receive data */
  906. X{
  907. X    static int      lastc;    /* last character seen */
  908. X
  909. X    switch (state) {    /* action depends on our state */
  910. X    case NOHIST:        /* no previous history */
  911. X        if (c == DLE)    /* if starting a series */
  912. X            state = INREP;    /* then remember it next time */
  913. X        else
  914. X            putc_unp(lastc = c, t);    /* else nothing unusual */
  915. X        return;
  916. X
  917. X    case INREP:        /* in a repeat */
  918. X        if (c)        /* if count is nonzero */
  919. X            while (--c)    /* then repeatedly ... */
  920. X                putc_unp(lastc, t);    /* ... output the byte */
  921. X        else
  922. X            putc_unp(DLE, t);    /* else output DLE as data */
  923. X        state = NOHIST;    /* back to no history */
  924. X        return;
  925. X
  926. X    default:
  927. X        abort("Bad NCR unpacking state (%d)", state);
  928. X    }
  929. X}
  930. X
  931. X/*
  932. X * This routine provides low-level byte input from an archive.  This routine
  933. X * MUST be used, as end-of-file is simulated at the end of the archive entry.
  934. X */
  935. X
  936. Xint
  937. Xgetc_unp(f)            /* get a byte from an archive */
  938. X    FILE           *f;    /* archive file to read */
  939. X{
  940. X    register int    xx;
  941. X    unsigned char        code();
  942. X
  943. X    if (!size)        /* if no data left */
  944. X        return EOF;    /* then pretend end of file */
  945. X
  946. X    size--;            /* deduct from input counter */
  947. X    xx = getc(f);
  948. X    return code(xx);    /* and return next decoded byte */
  949. X}
  950. ________This_Is_The_END________
  951. if test `wc -c < arcunp.c` -ne     5347; then
  952.     echo 'shar: arcunp.c was damaged during transit (should have been     5347 bytes)'
  953. fi
  954. fi        ; : end of overwriting check
  955. echo 'x - arcusq.c'
  956. if test -f arcusq.c; then echo 'shar: not overwriting arcusq.c'; else
  957. sed 's/^X//' << '________This_Is_The_END________' > arcusq.c
  958. X/*
  959. X * $Header: arcusq.c,v 1.2 88/06/02 16:27:44 hyc Locked $
  960. X */
  961. X
  962. X/*
  963. X * ARC - Archive utility - ARCUSQ
  964. X * 
  965. X * Version 3.14, created on 07/25/86 at 13:04:19
  966. X * 
  967. X * (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
  968. X * 
  969. X * By:  Thom Henderson
  970. X * 
  971. X * Description: This file contains the routines used to expand a file which was
  972. X * packed using Huffman squeezing.
  973. X * 
  974. X * Most of this code is taken from an USQ program by Richard Greenlaw, which was
  975. X * adapted to CI-C86 by Robert J. Beilstein.
  976. X * 
  977. X * Language: Computer Innovations Optimizing C86
  978. X */
  979. X#include <stdio.h>
  980. X#include "arc.h"
  981. X
  982. Xvoid    abort();
  983. Xint    getc_unp();
  984. X
  985. X/* stuff for Huffman unsqueezing */
  986. X
  987. X#define ERROR (-1)
  988. X
  989. X#define SPEOF 256        /* special endfile token */
  990. X#define NUMVALS 257        /* 256 data values plus SPEOF */
  991. X
  992. Xextern    struct nd {        /* decoding tree */
  993. X    int    child[2];    /* left, right */
  994. X}               node[NUMVALS];    /* use large buffer */
  995. X
  996. Xstatic int      bpos;        /* last bit position read */
  997. Xstatic int      curin;        /* last byte value read */
  998. Xstatic int      numnodes;    /* number of nodes in decode tree */
  999. X
  1000. Xstatic          short
  1001. Xget_int(f)            /* get a 16bit integer */
  1002. X    FILE           *f;    /* file to get it from */
  1003. X{
  1004. X    int    i,j;
  1005. X    i = getc_unp(f);
  1006. X    j = getc_unp(f) << 8;
  1007. X    return (i | j) & 0xFFFF;
  1008. X}
  1009. X
  1010. Xvoid
  1011. Xinit_usq(f)            /* initialize Huffman unsqueezing */
  1012. X    FILE           *f;    /* file containing squeezed data */
  1013. X{
  1014. X    int             i;    /* node index */
  1015. X
  1016. X    bpos = 99;        /* force initial read */
  1017. X
  1018. X    numnodes = get_int(f);
  1019. X
  1020. X    if (numnodes < 0 || numnodes >= NUMVALS)
  1021. X        abort("File has an invalid decode tree");
  1022. X
  1023. X    /* initialize for possible empty tree (SPEOF only) */
  1024. X
  1025. X    node[0].child[0] = -(SPEOF + 1);
  1026. X    node[0].child[1] = -(SPEOF + 1);
  1027. X
  1028. X    for (i = 0; i < numnodes; ++i) {    /* get decoding tree from
  1029. X                         * file */
  1030. X        node[i].child[0] = get_int(f);
  1031. X        node[i].child[1] = get_int(f);
  1032. X    }
  1033. X}
  1034. X
  1035. Xint
  1036. Xgetc_usq(f)            /* get byte from squeezed file */
  1037. X    FILE           *f;    /* file containing squeezed data */
  1038. X{
  1039. X    int             i;    /* tree index */
  1040. X
  1041. X    /* follow bit stream in tree to a leaf */
  1042. X
  1043. X    for (i = 0; i >= 0;) {    /* work down(up?) from root */
  1044. X        if (++bpos > 7) {
  1045. X            if ((curin = getc_unp(f)) == ERROR)
  1046. X                return (ERROR);
  1047. X            bpos = 0;
  1048. X
  1049. X            /* move a level deeper in tree */
  1050. X            i = node[i].child[1 & curin];
  1051. X        } else
  1052. X            i = node[i].child[1 & (curin >>= 1)];
  1053. X    }
  1054. X
  1055. X    /* decode fake node index to original data value */
  1056. X
  1057. X    i = -(i + 1);
  1058. X
  1059. X    /* decode special endfile token to normal EOF */
  1060. X
  1061. X    i = (i == SPEOF) ? EOF : i;
  1062. X    return i;
  1063. X}
  1064. ________This_Is_The_END________
  1065. if test `wc -c < arcusq.c` -ne     2484; then
  1066.     echo 'shar: arcusq.c was damaged during transit (should have been     2484 bytes)'
  1067. fi
  1068. fi        ; : end of overwriting check
  1069. echo 'x - dtime.c'
  1070. if test -f dtime.c; then echo 'shar: not overwriting dtime.c'; else
  1071. sed 's/^X//' << '________This_Is_The_END________' > dtime.c
  1072. X/* dtime.c - routines to do ``ARPA-style'' time structures
  1073. X
  1074. Xver  date   who remarks
  1075. X--- ------- --- -------------------------------------------------------------
  1076. X01B 15nov86 JP  Thouroughly hacked by Jef Poskanzer.
  1077. X01A ??????? MTR Original version from the MH 6.5 distribution, courtesy
  1078. X              of Marshall Rose.
  1079. X
  1080. X*/
  1081. X
  1082. X
  1083. X#include "tws.h"
  1084. X#include <stdio.h>
  1085. X#include <sys/types.h>
  1086. X#include <time.h>
  1087. X#ifdef  SYS5
  1088. X#include <string.h>
  1089. X#else SYS5
  1090. X#include <strings.h>
  1091. X#include <sys/timeb.h>
  1092. X#endif SYS5
  1093. X
  1094. X#ifdef    SYS5
  1095. Xextern int  daylight;
  1096. Xextern long timezone;
  1097. Xextern char *tzname[];
  1098. X#endif    SYS5
  1099. X
  1100. X/*   */
  1101. X
  1102. X#define    abs(a) ( a >= 0 ? a : -a )
  1103. X
  1104. Xchar *tw_moty[] = {
  1105. X    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  1106. X    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL };
  1107. X
  1108. Xchar *tw_dotw[] = {
  1109. X    "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", NULL };
  1110. X
  1111. Xchar *tw_ldotw[] = {
  1112. X    "Sunday", "Monday", "Tuesday", "Wednesday",
  1113. X    "Thursday", "Friday", "Saturday", NULL };
  1114. X
  1115. X/*   */
  1116. X
  1117. Xstatic struct zone
  1118. X    {
  1119. X    char *std;
  1120. X    char *dst;
  1121. X    int shift;
  1122. X    }
  1123. X    zones[] = {
  1124. X    "GMT", "BST", 0,
  1125. X    "EST", "EDT", -5,
  1126. X    "CST", "CDT", -6,
  1127. X    "MST", NULL, -7,
  1128. X    "PST", "PDT", -8,
  1129. X    "A", NULL, -1,
  1130. X    "B", NULL, -2,
  1131. X    "C", NULL, -3,
  1132. X    "D", NULL, -4,
  1133. X    "E", NULL, -5,
  1134. X    "F", NULL, -6,
  1135. X    "G", NULL, -7,
  1136. X    "H", NULL, -8,
  1137. X    "I", NULL, -9,
  1138. X    "K", NULL, -10,
  1139. X    "L", NULL, -11,
  1140. X    "M", NULL, -12,
  1141. X    "N", NULL, 1,
  1142. X#ifndef    HUJI
  1143. X    "O", NULL, 2,
  1144. X#else    HUJI
  1145. X    "JST", "JDT", 2,
  1146. X#endif    HUJI
  1147. X    "P", NULL, 3,
  1148. X    "Q", NULL, 4,
  1149. X    "R", NULL, 5,
  1150. X    "S", NULL, 6,
  1151. X    "T", NULL, 7,
  1152. X    "U", NULL, 8,
  1153. X    "V", NULL, 9,
  1154. X    "W", NULL, 10,
  1155. X    "X", NULL, 11,
  1156. X    "Y", NULL, 12,
  1157. X    NULL };
  1158. X
  1159. X#define CENTURY 19
  1160. X
  1161. Xlong time( );
  1162. Xstruct tm *localtime( );
  1163. X
  1164. X/*   */
  1165. X
  1166. Xchar *dtimenow( )
  1167. X    {
  1168. X    long clock;
  1169. X
  1170. X    (void) time( &clock );
  1171. X    return ( dtime( &clock ) );
  1172. X    }
  1173. X
  1174. X
  1175. Xchar *
  1176. Xdctime( tw )
  1177. Xstruct tws *tw;
  1178. X    {
  1179. X    static char buffer[25];
  1180. X
  1181. X    if ( tw == NULL )
  1182. X    return ( NULL );
  1183. X
  1184. X    (void) sprintf( buffer, "%.3s %.3s %02d %02d:%02d:%02d %.4d\n",
  1185. X        tw_dotw[tw -> tw_wday], tw_moty[tw -> tw_mon], tw -> tw_mday,
  1186. X        tw -> tw_hour, tw -> tw_min, tw -> tw_sec,
  1187. X        tw -> tw_year >= 100 ? tw -> tw_year : 1900 + tw -> tw_year );
  1188. X
  1189. X    return ( buffer );
  1190. X    }
  1191. X
  1192. X/*   */
  1193. X
  1194. Xstruct tws *
  1195. Xdtwstime( )
  1196. X    {
  1197. X    long clock;
  1198. X
  1199. X    (void) time( &clock );
  1200. X    return ( dlocaltime( &clock ) );
  1201. X    }
  1202. X
  1203. X
  1204. Xstruct tws *
  1205. Xdlocaltime( clock )
  1206. Xlong *clock;
  1207. X    {
  1208. X    register struct tm *tm;
  1209. X#ifndef SYS5
  1210. X    struct timeb tb;
  1211. X#endif not SYS5
  1212. X    static struct tws tw;
  1213. X
  1214. X    if ( clock == NULL )
  1215. X    return ( NULL );
  1216. X    tw.tw_flags = TW_NULL;
  1217. X
  1218. X    tm = localtime( clock );
  1219. X    tw.tw_sec = tm -> tm_sec;
  1220. X    tw.tw_min = tm -> tm_min;
  1221. X    tw.tw_hour = tm -> tm_hour;
  1222. X    tw.tw_mday = tm -> tm_mday;
  1223. X    tw.tw_mon = tm -> tm_mon;
  1224. X    tw.tw_year = tm -> tm_year;
  1225. X    tw.tw_wday = tm -> tm_wday;
  1226. X    tw.tw_yday = tm -> tm_yday;
  1227. X    if ( tm -> tm_isdst )
  1228. X    tw.tw_flags |= TW_DST;
  1229. X#ifndef  SYS5
  1230. X    ftime( &tb );
  1231. X    tw.tw_zone = -tb.timezone;
  1232. X#else   SYS5
  1233. X    tzset( );
  1234. X    tw.tw_zone = -(timezone / 60);
  1235. X#endif  SYS5
  1236. X    tw.tw_flags &= ~TW_SDAY;
  1237. X    tw.tw_flags |= TW_SEXP;
  1238. X    tw.tw_clock = *clock;
  1239. X
  1240. X    return ( &tw );
  1241. X    }
  1242. X
  1243. X
  1244. Xstruct tws *
  1245. Xdgmtime( clock )
  1246. Xlong *clock;
  1247. X    {
  1248. X    register struct tm *tm;
  1249. X    static struct tws tw;
  1250. X
  1251. X    if ( clock == NULL )
  1252. X    return ( NULL );
  1253. X    tw.tw_flags = TW_NULL;
  1254. X
  1255. X    tm = gmtime( clock );
  1256. X    tw.tw_sec = tm -> tm_sec;
  1257. X    tw.tw_min = tm -> tm_min;
  1258. X    tw.tw_hour = tm -> tm_hour;
  1259. X    tw.tw_mday = tm -> tm_mday;
  1260. X    tw.tw_mon = tm -> tm_mon;
  1261. X    tw.tw_year = tm -> tm_year;
  1262. X    tw.tw_wday = tm -> tm_wday;
  1263. X    tw.tw_yday = tm -> tm_yday;
  1264. X    if ( tm -> tm_isdst )
  1265. X    tw.tw_flags |= TW_DST;
  1266. X    tw.tw_zone = 0;
  1267. X    tw.tw_flags &= ~TW_SDAY;
  1268. X    tw.tw_flags |= TW_SEXP;
  1269. X    tw.tw_clock = *clock;
  1270. X
  1271. X    return( &tw );
  1272. X    }
  1273. X
  1274. X/*   */
  1275. X
  1276. Xchar *
  1277. Xdasctime( tw, flags )
  1278. Xstruct tws *tw;
  1279. Xint flags;
  1280. X    {
  1281. X    static char buffer[80], result[80];
  1282. X
  1283. X    if ( tw == NULL )
  1284. X    return ( NULL );
  1285. X
  1286. X    (void) sprintf( buffer, "%02d %s %02d %02d:%02d:%02d %s",
  1287. X        tw -> tw_mday, tw_moty[tw -> tw_mon], tw -> tw_year,
  1288. X        tw -> tw_hour, tw -> tw_min, tw -> tw_sec,
  1289. X        dtimezone( tw -> tw_zone, tw -> tw_flags | flags ) );
  1290. X
  1291. X    if ( (tw -> tw_flags & TW_SDAY) == TW_SEXP )
  1292. X    (void) sprintf( result, "%s, %s", tw_dotw[tw -> tw_wday], buffer );
  1293. X    else
  1294. X    if ( (tw -> tw_flags & TW_SDAY) == TW_SNIL )
  1295. X        (void) strcpy( result, buffer );
  1296. X    else
  1297. X        (void) sprintf( result, "%s (%s)", buffer, tw_dotw[tw -> tw_wday] );
  1298. X
  1299. X    return ( result );
  1300. X    }
  1301. X
  1302. X/*   */
  1303. X
  1304. Xchar *
  1305. Xdtimezone( offset, flags )
  1306. Xint offset, flags;
  1307. X    {
  1308. X    register int hours, mins;
  1309. X    register struct zone *z;
  1310. X    static char buffer[10];
  1311. X
  1312. X    if ( offset < 0 )
  1313. X    {
  1314. X    mins = -((-offset) % 60);
  1315. X    hours = -((-offset) / 60);
  1316. X    }
  1317. X    else
  1318. X    {
  1319. X    mins = offset % 60;
  1320. X    hours = offset / 60;
  1321. X    }
  1322. X
  1323. X    if ( !(flags & TW_ZONE) && mins == 0 )
  1324. X    for ( z = zones; z -> std; z++ )
  1325. X        if ( z -> shift == hours )
  1326. X        return ( z -> dst && (flags & TW_DST) ? z -> dst : z -> std );
  1327. X
  1328. X#ifdef    DSTXXX
  1329. X    if ( flags & TW_DST )
  1330. X    hours += 1;
  1331. X#endif    DSTXXX
  1332. X    (void) sprintf( buffer, "%s%02d%02d",
  1333. X        offset < 0 ? "-" : "+", abs( hours ), abs( mins ) );
  1334. X    return ( buffer );
  1335. X    }
  1336. X
  1337. X/*   */
  1338. X
  1339. Xvoid
  1340. Xtwscopy( tb, tw )
  1341. Xstruct tws *tb, *tw;
  1342. X    {
  1343. X#ifdef    notdef
  1344. X    tb -> tw_sec = tw -> tw_sec;
  1345. X    tb -> tw_min = tw -> tw_min;
  1346. X    tb -> tw_hour = tw -> tw_hour;
  1347. X    tb -> tw_mday = tw -> tw_mday;
  1348. X    tb -> tw_mon = tw -> tw_mon;
  1349. X    tb -> tw_year = tw -> tw_year;
  1350. X    tb -> tw_wday = tw -> tw_wday;
  1351. X    tb -> tw_yday = tw -> tw_yday;
  1352. X    tb -> tw_zone = tw -> tw_zone;
  1353. X    tb -> tw_clock = tw -> tw_clock;
  1354. X    tb -> tw_flags = tw -> tw_flags;
  1355. X#else    not notdef
  1356. X    *tb = *tw;
  1357. X#endif    not notdef
  1358. X    }
  1359. X
  1360. X
  1361. Xint
  1362. Xtwsort( tw1, tw2 )
  1363. Xstruct tws *tw1, *tw2;
  1364. X    {
  1365. X    register long c1, c2;
  1366. X
  1367. X    (void) twclock( tw1 );
  1368. X    (void) twclock( tw2 );
  1369. X
  1370. X    return ( (c1 = tw1 -> tw_clock) > (c2 = tw2 -> tw_clock) ? 1
  1371. X        : c1 == c2 ? 0 : -1 );
  1372. X    }
  1373. X
  1374. X/*   */
  1375. X
  1376. X
  1377. X/* Julian day number of the Unix* clock's origin, 01 Jan 1970. */
  1378. X#define JD1970 2440587L
  1379. X
  1380. X
  1381. Xlong
  1382. Xtwjuliandate( tw )
  1383. Xstruct tws *tw;
  1384. X    {
  1385. X    register int mday, mon, year;
  1386. X    register long a, b;
  1387. X    double jd;
  1388. X
  1389. X    if ( (mday = tw -> tw_mday) < 1 || mday > 31 ||
  1390. X        (mon = tw -> tw_mon + 1) < 1 || mon > 12 ||
  1391. X        (year = tw -> tw_year) < 1 || year > 10000 )
  1392. X    return ( -1L );
  1393. X    if ( year < 100 )
  1394. X    year += CENTURY * 100;
  1395. X
  1396. X    if ( mon == 1 || mon == 2 )
  1397. X    {
  1398. X    --year;
  1399. X    mon += 12;
  1400. X    }
  1401. X    if ( year < 1583 )
  1402. X    return ( -1L );
  1403. X    a = year / 100;
  1404. X    b = 2 - a + a / 4;
  1405. X    b += (long) ( (double) year * 365.25 );
  1406. X    b += (long) ( 30.6001 * ( (double) mon + 1.0 ) );
  1407. X    jd = mday + b + 1720994.5;
  1408. X    return ( (long) jd );
  1409. X    }
  1410. X
  1411. X
  1412. Xlong
  1413. Xtwsubdayclock( tw )
  1414. Xstruct tws *tw;
  1415. X    {
  1416. X    register int sec, min, hour;
  1417. X    register long result;
  1418. X
  1419. X    if ( (sec = tw -> tw_sec) < 0 || sec > 59 ||
  1420. X        (min = tw -> tw_min) < 0 || min > 59 ||
  1421. X        (hour = tw -> tw_hour) < 0 || hour > 23 )
  1422. X    return ( -1L );
  1423. X
  1424. X    result = ( hour * 60 + min ) * 60 + sec;
  1425. X    result -= 60 * tw -> tw_zone;
  1426. X    if ( tw -> tw_flags & TW_DST )
  1427. X    result -= 60 * 60;
  1428. X
  1429. X    return ( result );
  1430. X    }
  1431. X
  1432. X
  1433. Xlong
  1434. Xtwclock( tw )
  1435. Xstruct tws *tw;
  1436. X    {
  1437. X    register long jd, sdc, result;
  1438. X
  1439. X    if ( tw -> tw_clock != 0L )
  1440. X    return ( tw -> tw_clock );
  1441. X
  1442. X    if ( ( jd = twjuliandate( tw ) ) == -1L )
  1443. X    return ( tw -> tw_clock = -1L );
  1444. X    if ( ( sdc = twsubdayclock( tw ) ) == -1L )
  1445. X    return ( tw -> tw_clock = -1L );
  1446. X
  1447. X    result = ( jd - JD1970 ) * 24 * 60 * 60 + sdc;
  1448. X
  1449. X    return ( tw -> tw_clock = result );
  1450. X    }
  1451. X
  1452. X/*   */
  1453. X
  1454. X/*** twsubtract - subtract tw2 from tw1, returning result in seconds
  1455. X
  1456. XThe point of this routine is that using twclock( tw1 ) - twclock( tw2 )
  1457. Xwould limit you to dates after the Unix* Epoch ( 01 January 1970 ).  This
  1458. Xroutine avoids that limit.  However, because the result is represented
  1459. Xby 32 bits, it is still limited to a span of two billion seconds, which is
  1460. Xabout 66 years.
  1461. X
  1462. X*/
  1463. X
  1464. Xlong
  1465. Xtwsubtract( tw1, tw2 )
  1466. Xstruct tws *tw1, *tw2;
  1467. X    {
  1468. X    register long jd1, jd2, sdc1, sdc2, result;
  1469. X
  1470. X    if ( ( jd1 = twjuliandate( tw1 ) ) == -1L )
  1471. X    return ( 0L );
  1472. X    if ( ( sdc1 = twsubdayclock( tw1 ) ) == -1L )
  1473. X    return ( 0L );
  1474. X
  1475. X    if ( ( jd2 = twjuliandate( tw2 ) ) == -1L )
  1476. X    return ( 0L );
  1477. X    if ( ( sdc2 = twsubdayclock( tw2 ) ) == -1L )
  1478. X    return ( 0L );
  1479. X    
  1480. X    result = ( jd1 - jd2 ) * 24 * 60 * 60 + ( sdc1 - sdc2 );
  1481. X
  1482. X    return ( result );
  1483. X    }
  1484. X
  1485. X/*   */
  1486. X
  1487. X/*
  1488. X *    Simple calculation of day of the week.  Algorithm used is Zeller's
  1489. X *    congruence.  Currently, we assume if tw -> tw_year < 100
  1490. X *    then the century is CENTURY.
  1491. X */
  1492. X
  1493. Xset_dotw( tw )
  1494. Xstruct tws *tw;
  1495. X    {
  1496. X    register int month, day, year, century;
  1497. X
  1498. X    month = tw -> tw_mon - 1;
  1499. X    day = tw -> tw_mday;
  1500. X    year = tw -> tw_year % 100;
  1501. X    century = tw -> tw_year >= 100 ? tw -> tw_year / 100 : CENTURY;
  1502. X
  1503. X    if ( month <= 0 )
  1504. X    {
  1505. X    month += 12;
  1506. X    if ( --year < 0 )
  1507. X        {
  1508. X        year += 100;
  1509. X        century--;
  1510. X        }
  1511. X    }
  1512. X
  1513. X    tw -> tw_wday =
  1514. X    ((26 * month - 2) / 10 + day + year + year / 4
  1515. X        - 3 * century / 4 + 1) % 7;
  1516. X
  1517. X    tw -> tw_flags &= ~TW_SDAY;
  1518. X    tw -> tw_flags |= TW_SIMP;
  1519. X    }
  1520. X
  1521. X
  1522. X/* * Unix is a virus from outer space. */
  1523. ________This_Is_The_END________
  1524. if test `wc -c < dtime.c` -ne     9032; then
  1525.     echo 'shar: dtime.c was damaged during transit (should have been     9032 bytes)'
  1526. fi
  1527. fi        ; : end of overwriting check
  1528. echo 'x - dtimep.lex'
  1529. if test -f dtimep.lex; then echo 'shar: not overwriting dtimep.lex'; else
  1530. sed 's/^X//' << '________This_Is_The_END________' > dtimep.lex
  1531. X%e 2000
  1532. X%p 5000
  1533. X%n 1000
  1534. X%a 4000
  1535. X%START    Z
  1536. Xsun    (sun(day)?)
  1537. Xmon    (mon(day)?)
  1538. Xtue    (tue(sday)?)
  1539. Xwed    (wed(nesday)?)
  1540. Xthu    (thu(rsday)?)
  1541. Xfri    (fri(day)?)
  1542. Xsat    (sat(urday)?)
  1543. X
  1544. XDAY    ({sun}|{mon}|{tue}|{wed}|{thu}|{fri}|{sat})
  1545. X
  1546. Xjan    (jan(uary)?)
  1547. Xfeb    (feb(ruary)?)
  1548. Xmar    (mar(ch)?)
  1549. Xapr    (apr(il)?)
  1550. Xmay    (may)
  1551. Xjun    (jun(e)?)
  1552. Xjul    (jul(y)?)
  1553. Xaug    (aug(ust)?)
  1554. Xsep    (sep(tember)?)
  1555. Xoct    (oct(ober)?)
  1556. Xnov    (nov(ember)?)
  1557. Xdec    (dec(ember)?)
  1558. X
  1559. XMONTH    ({jan}|{feb}|{mar}|{apr}|{may}|{jun}|{jul}|{aug}|{sep}|{oct}|{nov}|{dec})
  1560. X
  1561. Xw    ([ \t]*)
  1562. XW    ([ \t]+)
  1563. XD    ([0-9]?[0-9])
  1564. Xd    [0-9]
  1565. X%{
  1566. X/* dtimep.lex - routines to do ``ARPA-style'' time parsing
  1567. X
  1568. Xver  date   who remarks
  1569. X--- ------- --- -------------------------------------------------------------
  1570. X01B 15nov86 JP  Thouroughly hacked by Jef Poskanzer.
  1571. X01A ??????? MTR Original version from the MH 6.5 distribution, courtesy
  1572. X              of Marshall Rose.
  1573. X
  1574. X*/
  1575. X
  1576. X#include "tws.h"
  1577. X#include <ctype.h>
  1578. X#include <sys/types.h>
  1579. X#include <time.h>
  1580. X#ifdef SYS5
  1581. X#include <string.h>
  1582. X#else SYS5
  1583. X#include <strings.h>
  1584. X#include <sys/timeb.h>
  1585. X#endif SYS5
  1586. X
  1587. X#ifdef SYS5
  1588. Xextern int  daylight;
  1589. Xextern long timezone;
  1590. Xextern char *tzname[];
  1591. X#endif SYS5
  1592. X
  1593. X/*
  1594. X * Table to convert month names to numeric month.  We use the
  1595. X * fact that the low order 5 bits of the sum of the 2nd & 3rd
  1596. X * characters of the name is a hash with no collisions for the 12
  1597. X * valid month names.  (The mask to 5 bits maps any combination of
  1598. X * upper and lower case into the same hash value).
  1599. X */
  1600. Xstatic int month_map[] = {
  1601. X    0,
  1602. X    6,    /* 1 - Jul */
  1603. X    3,    /* 2 - Apr */
  1604. X    5,    /* 3 - Jun */
  1605. X    0,
  1606. X    10,    /* 5 - Nov */
  1607. X    0,
  1608. X    1,    /* 7 - Feb */
  1609. X    11,    /* 8 - Dec */
  1610. X    0,
  1611. X    0,
  1612. X    0,
  1613. X    0,
  1614. X    0,
  1615. X    0,
  1616. X    0,    /*15 - Jan */
  1617. X    0,
  1618. X    0,
  1619. X    0,
  1620. X    2,    /*19 - Mar */
  1621. X    0,
  1622. X    8,    /*21 - Sep */
  1623. X    0,
  1624. X    9,    /*23 - Oct */
  1625. X    0,
  1626. X    0,
  1627. X    4,    /*26 - May */
  1628. X    0,
  1629. X    7 };    /*28 - Aug */
  1630. X/*
  1631. X * Same trick for day-of-week using the hash function
  1632. X *  (c1 & 7) + (c2 & 4)
  1633. X */
  1634. Xstatic int day_map[] = {
  1635. X    0,
  1636. X    0,
  1637. X    0,
  1638. X    6,    /* 3 - Sat */
  1639. X    4,    /* 4 - Thu */
  1640. X    0,
  1641. X    5,    /* 6 - Fri */
  1642. X    0,    /* 7 - Sun */
  1643. X    2,    /* 8 - Tue */
  1644. X    1    /* 9 - Mon */,
  1645. X    0,
  1646. X    3 };    /*11 - Wed */
  1647. X#define SETDAY tw.tw_wday= day_map[(cp[0] & 7) + (cp[1] & 4)];\
  1648. X        tw.tw_flags |= TW_SEXP;\
  1649. X        cp += 2;
  1650. X#define SETMONTH tw.tw_mon = month_map[(cp[0] + cp[1]) & 0x1f]; gotdate++;\
  1651. X         cp += 2;\
  1652. X         SKIPD;
  1653. X#define CVT1OR2 (i=(*cp++ - '0'), isdigit(*cp)? i*10 + (*cp++ - '0') : i)
  1654. X#define CVT2 ( (*cp++ - '0')*10 + (*cp++ - '0') )
  1655. X#define CVT3 ( ( (*cp++ - '0')*10 + (*cp++ - '0') )*10 + (*cp++ - '0') )
  1656. X#define CVT4 ( ( ( (*cp++ - '0')*10 + (*cp++ - '0') )*10 + (*cp++ - '0') )*10 + (*cp++ - '0') )
  1657. X#define SKIPD while ( ! isdigit( *cp++ ) ) ; --cp;
  1658. X#define ZONE(x) tw.tw_zone=(x);
  1659. X#define ZONED(x) tw.tw_zone=(x); tw.tw_flags |= TW_DST;
  1660. X#define LC(c) (isupper( c ) ? tolower( c ) : ( c ))
  1661. X%}
  1662. X%%
  1663. X%{
  1664. Xstruct tws *
  1665. Xdparsetime( str )
  1666. Xchar *str;
  1667. X    {
  1668. X    register int i;
  1669. X    static struct tws tw;
  1670. X    register char *cp;
  1671. X    register int gotdate = 0;
  1672. X#ifndef SYS5
  1673. X    struct timeb    tb;
  1674. X#endif not SYS5
  1675. X    long clock;
  1676. X
  1677. X    start_cond = 0;
  1678. X
  1679. X    /* Zero out the struct. */
  1680. X    bzero( (char *) &tw, sizeof tw );
  1681. X
  1682. X    /* Set default time zone. */
  1683. X#ifndef SYS5
  1684. X    ftime( &tb );
  1685. X    tw.tw_zone = -tb.timezone;
  1686. X#else SYS5
  1687. X    tzset( );
  1688. X    tw.tw_zone = -(timezone / 60);
  1689. X#endif SYS5
  1690. X
  1691. X    for ( ; ; )
  1692. X    switch ( cp = str, lex_string( &str, start_cond ) )
  1693. X        {
  1694. X        case -1:
  1695. X        if ( ! gotdate )
  1696. X            return ( NULL );
  1697. X        tw.tw_flags |= TW_JUNK;
  1698. X        /* fall through */
  1699. X        case 0:
  1700. X        if ( tw.tw_year == 0 )
  1701. X            {
  1702. X            /* Set default year. */
  1703. X            time( &clock );
  1704. X            tw.tw_year = localtime( &clock ) -> tm_year;
  1705. X            }
  1706. X        return ( &tw );
  1707. X
  1708. X%}
  1709. X{DAY}","?{w}                SETDAY;
  1710. X"("{DAY}")"(","?)            cp++, SETDAY;
  1711. X
  1712. X{D}(("-"{D}"-")|("/"{D}"/")){D}?{d}{d}{w}    {
  1713. X#ifdef EUROPE
  1714. X                    tw.tw_mday = CVT1OR2; cp++;
  1715. X                    tw.tw_mon  = CVT1OR2 - 1; cp++;
  1716. X#else EUROPE
  1717. X                    tw.tw_mon = CVT1OR2 - 1; cp++;
  1718. X                    tw.tw_mday  = CVT1OR2; cp++;
  1719. X#endif EUROPE
  1720. X                    for ( i = 0; isdigit( *cp ); )
  1721. X                        i = i * 10 + (*cp++ - '0');
  1722. X                    tw.tw_year = i;
  1723. X                    gotdate++;
  1724. X                    }
  1725. X{D}("/"|"-"){D}{w}            {
  1726. X#ifdef EUROPE
  1727. X                    tw.tw_mday = CVT1OR2; cp++;
  1728. X                    tw.tw_mon  = CVT1OR2 - 1;
  1729. X#else EUROPE
  1730. X                    tw.tw_mon = CVT1OR2 - 1; cp++;
  1731. X                    tw.tw_mday  = CVT1OR2;
  1732. X#endif EUROPE
  1733. X                    gotdate++;
  1734. X                    }
  1735. X{D}(("-"{MONTH}"-")|(" "{MONTH}" ")|({MONTH})){D}?{d}{d}({W}at)?{w}    {
  1736. X                    tw.tw_mday = CVT1OR2;
  1737. X                    while ( ! isalpha( *cp++ ) )
  1738. X                        ;
  1739. X                    SETMONTH;
  1740. X                    for ( i = 0; isdigit( *cp ); )
  1741. X                        i = i * 10 + (*cp++ - '0');
  1742. X                    tw.tw_year = i;
  1743. X                    gotdate++;
  1744. X                    }
  1745. X{D}"-"?{MONTH}({W}at)?{w}        {
  1746. X                    tw.tw_mday = CVT1OR2;
  1747. X                    while ( ! isalpha( *cp++ ) )
  1748. X                        ;
  1749. X                    SETMONTH;
  1750. X                    gotdate++;
  1751. X                    }
  1752. X{MONTH}{W}{D}","{W}{D}?{d}{d}{w}    {
  1753. X                    cp++;
  1754. X                    SETMONTH;
  1755. X                    tw.tw_mday = CVT1OR2;
  1756. X                    SKIPD;
  1757. X                    for ( i = 0; isdigit( *cp ); )
  1758. X                        i = i * 10 + (*cp++ - '0');
  1759. X                    tw.tw_year = i;
  1760. X                    gotdate++;
  1761. X                    }
  1762. X{MONTH}{W}{D}{w}            {
  1763. X                    cp++;
  1764. X                    SETMONTH;
  1765. X                    tw.tw_mday = CVT1OR2;
  1766. X                    gotdate++;
  1767. X                    }
  1768. X
  1769. X{D}:{D}:{D}({w}am)?{w}            {
  1770. X                    tw.tw_hour = CVT1OR2; cp++;
  1771. X                    tw.tw_min  = CVT1OR2; cp++;
  1772. X                    tw.tw_sec  = CVT1OR2;
  1773. X                    BEGIN Z;
  1774. X                    }
  1775. X{D}:{D}:{D}{w}pm{w}            {
  1776. X                    tw.tw_hour = CVT1OR2 + 12; cp++;
  1777. X                    tw.tw_min  = CVT1OR2; cp++;
  1778. X                    tw.tw_sec  = CVT1OR2;
  1779. X                    BEGIN Z;
  1780. X                    }
  1781. X{D}:{D}({w}am)?{w}            {
  1782. X                    tw.tw_hour = CVT1OR2; cp++;
  1783. X                    tw.tw_min  = CVT1OR2;
  1784. X                    BEGIN Z;
  1785. X                    }
  1786. X{D}:{D}{w}pm{w}                {
  1787. X                    tw.tw_hour = CVT1OR2 + 12; cp++;
  1788. X                    tw.tw_min  = CVT1OR2;
  1789. X                    BEGIN Z;
  1790. X                    }
  1791. X[0-2]{d}{d}{d}{d}{d}{w}            {
  1792. X                    tw.tw_hour = CVT1OR2;
  1793. X                    tw.tw_min  = CVT1OR2;
  1794. X                    tw.tw_sec  = CVT1OR2;
  1795. X                    BEGIN Z;
  1796. X                    }
  1797. X[0-2]{d}{d}{d}{w}            {
  1798. X                    tw.tw_hour = CVT1OR2;
  1799. X                    tw.tw_min  = CVT1OR2;
  1800. X                    BEGIN Z;
  1801. X                    }
  1802. X<Z>"-"?ut                ZONE(0 * 60);
  1803. X<Z>"-"?gmt                ZONE(0 * 60);
  1804. X<Z>"-"?jst                ZONE(2 * 60);
  1805. X<Z>"-"?jdt                ZONED(2 * 60);
  1806. X<Z>"-"?est                ZONE(-5 * 60);
  1807. X<Z>"-"?edt                ZONED(-5 * 60);
  1808. X<Z>"-"?cst                ZONE(-6 * 60);
  1809. X<Z>"-"?cdt                ZONED(-6 * 60);
  1810. X<Z>"-"?mst                ZONE(-7 * 60);
  1811. X<Z>"-"?mdt                ZONED(-7 * 60);
  1812. X<Z>"-"?pst                ZONE(-8 * 60);
  1813. X<Z>"-"?pdt                ZONED(-8 * 60);
  1814. X<Z>"-"?nst                ZONE(-(3 * 60 + 30));
  1815. X<Z>"-"?ast                ZONE(-4 * 60);
  1816. X<Z>"-"?adt                ZONED(-4 * 60);
  1817. X<Z>"-"?yst                ZONE(-9 * 60);
  1818. X<Z>"-"?ydt                ZONED(-9 * 60);
  1819. X<Z>"-"?hst                ZONE(-10 * 60);
  1820. X<Z>"-"?hdt                ZONED(-10 * 60);
  1821. X<Z>"-"?bst                ZONED(-1 * 60);
  1822. X<Z>[a-i]                tw.tw_zone = 60 * (('a'-1) - LC (*cp));
  1823. X<Z>[k-m]                tw.tw_zone = 60 * ('a' - LC (*cp));
  1824. X<Z>[n-y]                tw.tw_zone = 60 * (LC (*cp) - 'm');
  1825. X<Z>"+"[0-1]{d}{d}{d}            {
  1826. X                    cp++;
  1827. X                    tw.tw_zone = ((cp[0] * 10 + cp[1])
  1828. X                             -('0' * 10   + '0'))*60
  1829. X                            +((cp[2] * 10 + cp[3])
  1830. X                             -('0' * 10   + '0'));
  1831. X#ifdef DSTXXX
  1832. X                    zonehack (&tw);
  1833. X#endif DSTXXX
  1834. X                    cp += 4;
  1835. X                    }
  1836. X<Z>"-"[0-1]{d}{d}{d}            {
  1837. X                    cp++;
  1838. X                    tw.tw_zone = (('0' * 10   + '0')
  1839. X                             -(cp[0] * 10 + cp[1]))*60
  1840. X                            +(('0' * 10   + '0')
  1841. X                             -(cp[2] * 10 + cp[3]));
  1842. X#ifdef DSTXXX
  1843. X                    zonehack (&tw);
  1844. X#endif DSTXXX
  1845. X                    cp += 4;
  1846. X                    }
  1847. X
  1848. X<Z>{W}{d}{d}{d}{d}            {
  1849. X                    SKIPD;
  1850. X                    tw.tw_year = CVT4;
  1851. X                    }
  1852. X\n    |
  1853. X{W}    ;
  1854. X%%
  1855. X
  1856. X#ifdef DSTXXX
  1857. Xstatic
  1858. Xzonehack( tw )
  1859. Xregister struct tws *tw;
  1860. X    {
  1861. X    register struct tm *tm;
  1862. X
  1863. X    if ( twclock( tw ) == -1L )
  1864. X    return;
  1865. X
  1866. X    tm = localtime( &tw -> tw_clock );
  1867. X    if ( tm -> tm_isdst )
  1868. X    {
  1869. X    tw -> tw_flags |= TW_DST;
  1870. X    tw -> tw_zone -= 60;
  1871. X    }
  1872. X    }
  1873. X#endif DSTXXX
  1874. X
  1875. X
  1876. X#ifdef SYS5
  1877. X/* Not all SYS5's have bzero( ). */
  1878. X
  1879. Xbzero( b, length )
  1880. Xchar *b;
  1881. Xint length;
  1882. X    {
  1883. X    while ( length-- > 0 )
  1884. X    *b++ = 0;
  1885. X    }
  1886. X#endif
  1887. ________This_Is_The_END________
  1888. if test `wc -c < dtimep.lex` -ne     7327; then
  1889.     echo 'shar: dtimep.lex was damaged during transit (should have been     7327 bytes)'
  1890. fi
  1891. fi        ; : end of overwriting check
  1892. echo 'x - lexedit.sed'
  1893. if test -f lexedit.sed; then echo 'shar: not overwriting lexedit.sed'; else
  1894. sed 's/^X//' << '________This_Is_The_END________' > lexedit.sed
  1895. X2,/^extern int yylineno;$/c\
  1896. Xstatic int start_cond = 0;\
  1897. X#define BEGIN start_cond =
  1898. X/^struct yysvf \*yyestate;$/,/^extern struct yysvf yysvec/d
  1899. X/^# define YYNEWLINE /,/^int nstr;/d
  1900. X/^while((nstr = yylook()/,/^if(yywrap()) /d
  1901. X/^case -1:$/,/^fprintf(yyout,"bad switch yylook /c\
  1902. X    default: return(0);
  1903. X/^struct yysvf *yybgin = yysvec+1;$/d
  1904. X/^int yylineno /,$d
  1905. ________This_Is_The_END________
  1906. if test `wc -c < lexedit.sed` -ne      356; then
  1907.     echo 'shar: lexedit.sed was damaged during transit (should have been      356 bytes)'
  1908. fi
  1909. fi        ; : end of overwriting check
  1910. echo 'x - lexstring.c'
  1911. if test -f lexstring.c; then echo 'shar: not overwriting lexstring.c'; else
  1912. sed 's/^X//' << '________This_Is_The_END________' > lexstring.c
  1913. X#include <stdio.h>
  1914. X#include <ctype.h>
  1915. X
  1916. X#define YYLERR yysvec
  1917. X#define YYTYPE int
  1918. X#define YYLMAX 256
  1919. X
  1920. Xstruct yysvf { 
  1921. X    struct yywork *yystoff;
  1922. X    struct yysvf *yyother;
  1923. X    int *yystops;
  1924. X};
  1925. X
  1926. Xstruct yywork { 
  1927. X    YYTYPE    verify;
  1928. X    YYTYPE    advance; 
  1929. X}; 
  1930. X
  1931. Xextern int yyvstop[];
  1932. Xextern struct yywork yycrank[];
  1933. Xextern struct yysvf yysvec[];
  1934. Xextern struct yywork *yytop;
  1935. Xextern char yymatch[];
  1936. Xextern char yyextra[];
  1937. X
  1938. X#ifdef LEXDEBUG
  1939. Xstatic int debug = 0;
  1940. X#endif
  1941. X
  1942. Xlex_string( strptr, start_cond)
  1943. X    char    **strptr;
  1944. X    int    start_cond;
  1945. X{
  1946. X    register struct yysvf *state, **lsp;
  1947. X    register struct yywork *tran;
  1948. X    register int ch;
  1949. X    register char    *cp = *strptr;
  1950. X    register int    *found;
  1951. X    struct    yysvf *yylstate[YYLMAX];
  1952. X
  1953. X    /* start off machines */
  1954. X    lsp = yylstate;
  1955. X    state = yysvec+1+start_cond;
  1956. X    for (;;){
  1957. X#ifdef LEXDEBUG
  1958. X        if(debug)
  1959. X            fprintf(stderr,"state %d\n",state-yysvec-1);
  1960. X#endif
  1961. X        tran = state->yystoff;
  1962. X        if(tran == yycrank)
  1963. X            /* may not be any transitions */
  1964. X            if (state->yyother == 0 ||
  1965. X                state->yyother->yystoff == yycrank)
  1966. X                break;
  1967. X
  1968. X        ch = *cp++;
  1969. X#ifdef ONECASE
  1970. X        if (isupper(ch) )
  1971. X            ch = tolower(ch);
  1972. X#endif
  1973. Xtryagain:
  1974. X#ifdef LEXDEBUG
  1975. X        if(debug){
  1976. X            fprintf(stderr,"char ");
  1977. X            allprint(ch);
  1978. X            putchar('\n');
  1979. X        }
  1980. X#endif
  1981. X        if ( tran > yycrank){
  1982. X            tran += ch;
  1983. X            if (tran <= yytop && tran->verify+yysvec == state){
  1984. X                if ((state = tran->advance+yysvec) == YYLERR){
  1985. X                    /* error transitions */
  1986. X                    --cp;
  1987. X                    break;
  1988. X                }
  1989. X                *lsp++ = state;
  1990. X                goto contin;
  1991. X            }
  1992. X
  1993. X        } else if(tran < yycrank) {
  1994. X            /* r < yycrank */
  1995. X            tran = yycrank+(yycrank-tran) + ch;
  1996. X#ifdef LEXDEBUG
  1997. X            if (debug)
  1998. X                fprintf(stderr,"compressed state\n");
  1999. X#endif
  2000. X            if(tran <= yytop && tran->verify+yysvec == state){
  2001. X                if ((state = tran->advance+yysvec) == YYLERR)
  2002. X                    /* error transitions */
  2003. X                    break;
  2004. X
  2005. X                *lsp++ = state;
  2006. X                goto contin;
  2007. X            }
  2008. X            tran += (yymatch[ch] - ch);
  2009. X#ifdef LEXDEBUG
  2010. X            if(debug){
  2011. X                fprintf(stderr,"try fall back character ");
  2012. X                allprint(yymatch[ch]);
  2013. X                putchar('\n');
  2014. X            }
  2015. X#endif
  2016. X            if(tran <= yytop && tran->verify+yysvec == state){
  2017. X                if(tran->advance+yysvec == YYLERR)
  2018. X                    /* error transition */
  2019. X                    break;
  2020. X
  2021. X                *lsp++ = state = tran->advance+yysvec;
  2022. X                goto contin;
  2023. X            }
  2024. X        }
  2025. X        if ((state = state->yyother) &&
  2026. X            (tran = state->yystoff) != yycrank){
  2027. X#ifdef LEXDEBUG
  2028. X            if(debug)
  2029. X                fprintf(stderr,"fall back to state %d\n",
  2030. X                    state-yysvec-1);
  2031. X#endif
  2032. X            goto tryagain;
  2033. X        } else
  2034. X            break;
  2035. X
  2036. Xcontin:
  2037. X#ifdef LEXDEBUG
  2038. X        if(debug){
  2039. X            fprintf(stderr,"state %d char ",state-yysvec-1);
  2040. X            allprint(ch);
  2041. X            putchar('\n');
  2042. X        }
  2043. X#endif
  2044. X        ;
  2045. X    }
  2046. X#ifdef LEXDEBUG
  2047. X    if(debug){
  2048. X        fprintf(stderr,"stopped at %d with ",*(lsp-1)-yysvec-1);
  2049. X        allprint(ch);
  2050. X        putchar('\n');
  2051. X    }
  2052. X#endif
  2053. X    while (lsp-- > yylstate){
  2054. X        if (*lsp != 0 && (found= (*lsp)->yystops) && *found > 0){
  2055. X            if(yyextra[*found]){
  2056. X                /* must backup */
  2057. X                ch = -*found;
  2058. X                do {
  2059. X                    while (*found && *found++ != ch)
  2060. X                        ;
  2061. X                 } while (lsp > yylstate &&
  2062. X                      (found = (*--lsp)->yystops));
  2063. X            }
  2064. X#ifdef LEXDEBUG
  2065. X            if(debug){
  2066. X                fprintf(stderr,"\nmatch ");
  2067. X                for ( cp = *strptr;
  2068. X                      cp <= ((*strptr)+(lsp-yylstate));
  2069. X                      cp++)
  2070. X                    allprint( *cp );
  2071. X                fprintf(stderr," action %d\n",*found);
  2072. X            }
  2073. X#endif
  2074. X            *strptr += (lsp - yylstate + 1);
  2075. X            return(*found);
  2076. X        }
  2077. X    }
  2078. X    /* the string didn't match anything - if we're looking at
  2079. X     * eos, just return 0.  Otherwise, bump the string pointer
  2080. X     * and return -1.
  2081. X     */
  2082. X#ifdef LEXDEBUG
  2083. X    if(debug)
  2084. X        fprintf(stderr,"\nno match\n");
  2085. X#endif
  2086. X    if ( **strptr ) {
  2087. X        (*strptr)++;
  2088. X        return (-1);
  2089. X    }
  2090. X    return (0);
  2091. X}
  2092. X
  2093. X#ifdef LEXDEBUG
  2094. Xallprint(c)
  2095. X    char c;
  2096. X{
  2097. X    if ( c < 32 ) {
  2098. X        putc( '^', stderr );
  2099. X        c += 32;
  2100. X    } else if ( c == 127 ) {
  2101. X        putc( '^', stderr );
  2102. X        c = '?';
  2103. X    }
  2104. X    putc( c, stderr );
  2105. X}
  2106. X#endif
  2107. ________This_Is_The_END________
  2108. if test `wc -c < lexstring.c` -ne     3713; then
  2109.     echo 'shar: lexstring.c was damaged during transit (should have been     3713 bytes)'
  2110. fi
  2111. fi        ; : end of overwriting check
  2112. echo 'x - libtws.3'
  2113. if test -f libtws.3; then echo 'shar: not overwriting libtws.3'; else
  2114. sed 's/^X//' << '________This_Is_The_END________' > libtws.3
  2115. X.TH libtws 3 "08 November 1986"
  2116. X.SH NAME
  2117. Xlibtws \- alternate date and time routines including parsing
  2118. X.SH SYNOPSIS
  2119. X.nf
  2120. X.fc ^ ~
  2121. X.ta \w'char *dtimezone( offset, flags );  'u
  2122. Xinclude "tws.h"
  2123. X.PP
  2124. X^struct tws *dlocaltime( clock );~^/* local clock into tws */
  2125. Xlong *clock;
  2126. X.PP
  2127. X^struct tws *gmtime( clock );~^/* GMT clock into tws */
  2128. Xlong *clock;
  2129. X.PP
  2130. X^char *dtime( clock );~^/* clock into string */
  2131. Xlong *clock;
  2132. X.PP
  2133. X^long twclock( t );~^/* tws into clock */
  2134. Xstruct tws *t;
  2135. X.PP
  2136. X^long twjuliandate( t );~^/* tws into Julian day number */
  2137. Xstruct tws *t;
  2138. X.PP
  2139. X^struct tws *dparsetime( str );~^/* string into tws */
  2140. Xchar *str;
  2141. X.PP
  2142. X^char *dctime( t );~^/* tws into string */
  2143. Xstruct tws *t;
  2144. X.PP
  2145. X^char *dasctime( t, flags );~^/* tws into string */
  2146. Xstruct tws *t;
  2147. Xint flags;
  2148. X.PP
  2149. X^char *dtimezone( offset, flags );~^/* timezone into string */
  2150. Xint offset, flags;
  2151. X.PP
  2152. X^char *dtwszone( t );~^/* tws's timezone into string */
  2153. Xstruct tws *t;
  2154. X.PP
  2155. X^char *dtimemow( );~^/* current time into string */
  2156. X.PP
  2157. X^struct tws *dtwstime( );~^/* current time into tws */
  2158. X.PP
  2159. X^void twscopy( tot, fromt );~^/* copy a tws */
  2160. Xstruct tws *tot, *fromt;
  2161. X.PP
  2162. X^int twsort( t1, t2 );~^/* compare two tws's */
  2163. Xstruct tws *t1, *t2;
  2164. X.PP
  2165. X^long twsubtract( t1, t2 );~^/* seconds between t2 and t1 */
  2166. Xstruct tws *t1, *t2;
  2167. X.fi
  2168. X.SH DESCRIPTION
  2169. X.I Libtws
  2170. Xis a fairly complete date/time library.
  2171. XUnlike the standard Unix* date/time routines,
  2172. X.I libtws
  2173. Xwill parse date/time strings into internal form.
  2174. XThe format for specifying date/time strings is pretty loose - basically
  2175. Xthe same as the format for date/times in network mail.
  2176. X.PP
  2177. XMost of the routines do not use the Unix* "clock" time
  2178. Xformat, and therefore are not limited to dates after 01 January 1970.
  2179. XIn particular, twsubtract() lets you subtract two dates without
  2180. Xconverting them to "clock" form.
  2181. X.SH "SEE\ ALSO"
  2182. X.IR ctime(3),
  2183. X.IR time(3)
  2184. X.SH AUTHOR
  2185. XMost of
  2186. X.I libtws
  2187. Xcame from version 6.5 of the MH message
  2188. Xhandling system, courtesy of Marshall Rose.
  2189. XSome improvements (?) were added by Jef Poskanzer.
  2190. X.SH BUGS
  2191. XThe return values point to static data whose contents are overwritten
  2192. Xby the next call.
  2193. X.PP
  2194. XThe basic Unix* time format (clock) only goes back to 1970, limiting
  2195. Xapplications somewhat.
  2196. X.SH NOTE
  2197. X* Unix is a virus from outer space.
  2198. ________This_Is_The_END________
  2199. if test `wc -c < libtws.3` -ne     2241; then
  2200.     echo 'shar: libtws.3 was damaged during transit (should have been     2241 bytes)'
  2201. fi
  2202. fi        ; : end of overwriting check
  2203. echo 'x - marc.c'
  2204. if test -f marc.c; then echo 'shar: not overwriting marc.c'; else
  2205. sed 's/^X//' << '________This_Is_The_END________' > marc.c
  2206. X/*
  2207. X * $Header: marc.c,v 1.2 88/06/06 01:05:02 hyc Locked $
  2208. X */
  2209. X
  2210. X/*  MARC - Archive merge utility
  2211. X
  2212. X    Version 5.21, created on 04/22/87 at 15:05:10
  2213. X
  2214. X(C) COPYRIGHT 1985-87 by System Enhancement Associates; ALL RIGHTS RESERVED
  2215. X
  2216. X    By:     Thom Henderson
  2217. X
  2218. X    Description:
  2219. X     This program is used to "merge" archives.  That is, to move
  2220. X     files from one archive to another with no data conversion.
  2221. X     Please refer to the ARC source for a description of archives
  2222. X     and archive formats.
  2223. X
  2224. X    Instructions:
  2225. X     Run this program with no arguments for complete instructions.
  2226. X
  2227. X    Language:
  2228. X     Computer Innovations Optimizing C86
  2229. X*/
  2230. X#include <stdio.h>
  2231. X#include "arc.h"
  2232. X
  2233. XFILE *src;                   /* source archive */
  2234. Xchar srcname[STRLEN];               /* source archive name */
  2235. X
  2236. Xstatic char **lst;               /* files list */
  2237. Xstatic int lnum;               /* length of files list */
  2238. X
  2239. X
  2240. Xmain(nargs,arg)                   /* system entry point */
  2241. Xint nargs;                   /* number of arguments */
  2242. Xchar *arg[];                   /* pointers to arguments */
  2243. X{
  2244. X    char *makefnam();               /* filename fixup routine */
  2245. X    char *calloc();               /* memory manager */
  2246. X    char *envfind();
  2247. X#if    !MTS
  2248. X    char *arctemp2, *mktemp();        /* temp file stuff */
  2249. X#endif
  2250. X#if    GEMDOS
  2251. X    void exitpause();
  2252. X#endif
  2253. X    int n;                   /* index */
  2254. X
  2255. X    if(nargs<3)
  2256. X    {     printf("MARC - Archive merger, Version 5.21, created on 04/22/87 at 15:05:10\n");
  2257. X/*     printf("(C) COPYRIGHT 1985,86,87 by System Enhancement Associates;");
  2258. X     printf(" ALL RIGHTS RESERVED\n\n");
  2259. X     printf("Please refer all inquiries to:\n\n");
  2260. X     printf("    System Enhancement Associates\n");
  2261. X     printf("    21 New Street, Wayne NJ 07470\n\n");
  2262. X     printf("You may copy and distribute this program freely,");
  2263. X     printf(" provided that:\n");
  2264. X     printf("    1)      No fee is charged for such copying and");
  2265. X     printf(" distribution, and\n");
  2266. X     printf("    2)      It is distributed ONLY in its original,");
  2267. X     printf(" unmodified state.\n\n");
  2268. X     printf("If you like this program, and find it of use, then your");
  2269. X     printf(" contribution will\n");
  2270. X     printf("be appreciated.  You may not use this product in a");
  2271. X     printf(" commercial environment\n");
  2272. X     printf("or a governmental organization without paying a license");
  2273. X     printf(" fee of $35.  Site\n");
  2274. X     printf("licenses and commercial distribution licenses are");
  2275. X     printf(" available.  A program\n");
  2276. X     printf("disk and printed documentation are available for $50.\n");
  2277. X     printf("\nIf you fail to abide by the terms of this license, ");
  2278. X     printf(" then your conscience\n");
  2279. X     printf("will haunt you for the rest of your life.\n\n");
  2280. X*/
  2281. X     printf("Usage: MARC <tgtarc> <srcarc> [<filename> . . .]\n");
  2282. X     printf("Where: <tgtarc> is the archive to add files to,\n");
  2283. X     printf("    <srcarc> is the archive to get files from, and\n");
  2284. X     printf("    <filename> is zero or more file names to get.\n");
  2285. X     printf("\nAdapted from MSDOS by Howard Chu\n");
  2286. X#if    GEMDOS
  2287. X     exitpause();
  2288. X#endif
  2289. X     return 1;
  2290. X    }
  2291. X
  2292. X    /* see where temp files go */
  2293. X#if    !MTS
  2294. X    arctemp = calloc(1, STRLEN);
  2295. X    if (!(arctemp2 = envfind("ARCTEMP")))
  2296. X        arctemp2 = envfind("TMPDIR");
  2297. X    if (arctemp2) {
  2298. X        strcpy(arctemp, arctemp2);
  2299. X        n = strlen(arctemp);
  2300. X        if (arctemp[n - 1] != CUTOFF)
  2301. X            arctemp[n] = CUTOFF;
  2302. X    }
  2303. X#if    !MSDOS
  2304. X    strcat(arctemp, mktemp("AXXXXXX"));
  2305. X#else
  2306. X    strcat(arctemp, "$ARCTEMP");
  2307. X#endif
  2308. X#else
  2309. X    guinfo("SHFSEP    ", gotinf);
  2310. X    sepchr[0] = gotinf[0];
  2311. X    guinfo("SCRFCHAR", gotinf);
  2312. X    tmpchr[0] = gotinf[0];
  2313. X    arctemp = "-$$$";
  2314. X    arctemp[0] = tmpchr[0];
  2315. X#endif
  2316. X
  2317. X    makefnam(arg[1],".arc",arcname);   /* fix up archive names */
  2318. X    makefnam(arg[2],".arc",srcname);
  2319. X/*    makefnam(".$$$",arcname,newname);*/
  2320. X    sprintf(newname,"%s.arc",arctemp);
  2321. X
  2322. X#if    !UNIX
  2323. X    upper(arcname); upper(srcname); upper(newname);
  2324. X#endif
  2325. X
  2326. X    arc = fopen(arcname,"rb");           /* open the archives */
  2327. X    if(!(src=fopen(srcname,"rb")))
  2328. X     abort("Cannot read source archive %s",srcname);
  2329. X    if(!(new=fopen(newname,"wb")))
  2330. X     abort("Cannot create new archive %s",newname);
  2331. X
  2332. X    if(!arc)
  2333. X     printf("Creating new archive %s\n",arcname);
  2334. X
  2335. X    /* get the files list set up */
  2336. X
  2337. X    lnum = nargs-3;               /* initial length of list */
  2338. X    if(lnum<1)                   /* phoney for default case */
  2339. X    {     lnum = 1;
  2340. X     lst = (char **) calloc(1,sizeof(char *));
  2341. X     lst[0] = "*.*";
  2342. X    }
  2343. X    else                   /* else use filenames given */
  2344. X    {     lst = (char **) calloc(lnum,sizeof(char *));
  2345. X     for(n=3; n<nargs; n++)
  2346. X          lst[n-3] = arg[n];
  2347. X
  2348. X     for(n=0; n<lnum; )           /* expand indirect references */
  2349. X     {    if(*lst[n] == '@')
  2350. X           expandlst(n);
  2351. X          else n++;
  2352. X     }
  2353. X    }
  2354. X
  2355. X    merge(lnum,lst);               /* merge desired files */
  2356. X
  2357. X    if(arc) fclose(arc);           /* close the archives */
  2358. X    fclose(src);
  2359. X    fclose(new);
  2360. X
  2361. X    if(arc)                   /* make the switch */
  2362. X     if(unlink(arcname))
  2363. X          abort("Unable to delete old copy of %s",arcname);
  2364. X    if(move(newname,arcname))
  2365. X     abort("Unable to rename %s to %s",newname,arcname);
  2366. X
  2367. X    setstamp(arcname,arcdate,arctime);     /* new arc matches newest file */
  2368. X
  2369. X#if    GEMDOS
  2370. X    exitpause();
  2371. X#endif
  2372. X    return nerrs;
  2373. X}
  2374. X
  2375. Xmerge(nargs,arg)               /* merge two archives */
  2376. Xint nargs;                   /* number of filename templates */
  2377. Xchar *arg[];                   /* pointers to names */
  2378. X{
  2379. X    struct heads srch;               /* source archive header */
  2380. X    struct heads arch;               /* target archive header */
  2381. X    int gotsrc, gotarc;               /* archive entry versions (0=end) */
  2382. X    int copy;                   /* true to copy file from source */
  2383. X    int n;                   /* index */
  2384. X
  2385. X    gotsrc = gethdr(src,&srch);           /* get first source file */
  2386. X    gotarc = gethdr(arc,&arch);           /* get first target file */
  2387. X
  2388. X    while(gotsrc || gotarc)           /* while more to merge */
  2389. X    {     if(strcmp(srch.name,arch.name)>0)
  2390. X     {    copyfile(arc,&arch,gotarc);
  2391. X          gotarc = gethdr(arc,&arch);
  2392. X     }
  2393. X
  2394. X     else if(strcmp(srch.name,arch.name)<0)
  2395. X     {    copy = 0;
  2396. X          for(n=0; n<nargs; n++)
  2397. X          {       if(match(srch.name,arg[n]))
  2398. X           {    copy = 1;
  2399. X            break;
  2400. X           }
  2401. X          }
  2402. X          if(copy)               /* select source or target */
  2403. X          {       printf("Adding file:      %s\n",srch.name);
  2404. X           copyfile(src,&srch,gotsrc);
  2405. X          }
  2406. X          else fseek(src,srch.size,1);
  2407. X          gotsrc = gethdr(src,&srch);
  2408. X     }
  2409. X
  2410. X     else                   /* duplicate names */
  2411. X     {    copy = 0;
  2412. X          {       if((srch.date>arch.date)
  2413. X           || (srch.date==arch.date && srch.time>arch.time))
  2414. X           {    for(n=0; n<nargs; n++)
  2415. X            {    if(match(srch.name,arg[n]))
  2416. X                 {      copy = 1;
  2417. X                  break;
  2418. X                 }
  2419. X            }
  2420. X           }
  2421. X          }
  2422. X          if(copy)               /* select source or target */
  2423. X          {       printf("Updating file: %s\n",srch.name);
  2424. X           copyfile(src,&srch,gotsrc);
  2425. X           gotsrc = gethdr(src,&srch);
  2426. X           if(gotarc)
  2427. X           {    fseek(arc,arch.size,1);
  2428. X            gotarc = gethdr(arc,&arch);
  2429. X           }
  2430. X          }
  2431. X          else
  2432. X          {       copyfile(arc,&arch,gotarc);
  2433. X           gotarc = gethdr(arc,&arch);
  2434. X           if(gotsrc)
  2435. X           {    fseek(src,srch.size,1);
  2436. X            gotsrc = gethdr(src,&srch);
  2437. X           }
  2438. X          }
  2439. X     }
  2440. X    }
  2441. X
  2442. X    hdrver = 0;                   /* end of archive marker */
  2443. X    writehdr(&arch,new);           /* mark the end of the archive */
  2444. X}
  2445. X
  2446. Xint gethdr(f,hdr)               /* special read header for merge */
  2447. XFILE *f;                   /* file to read from */
  2448. Xstruct heads *hdr;               /* storage for header */
  2449. X{
  2450. X    char *i = hdr->name;           /* string index */
  2451. X    int n;                   /* index */
  2452. X
  2453. X    for(n=0; n<FNLEN; n++)           /* fill name field */
  2454. X     *i++ = 0176;               /* impossible high value */
  2455. X    *--i = '\0';               /* properly end the name */
  2456. X
  2457. X    hdrver = 0;                   /* reset header version */
  2458. X    if(readhdr(hdr,f))               /* use normal reading logic */
  2459. X     return hdrver;               /* return the version */
  2460. X    else return 0;               /* or fake end of archive */
  2461. X}
  2462. X
  2463. Xcopyfile(f,hdr,ver)               /* copy a file from an archive */
  2464. XFILE *f;                   /* archive to copy from */
  2465. Xstruct heads *hdr;               /* header data for file */
  2466. Xint ver;                   /* header version */
  2467. X{
  2468. X    hdrver = ver;               /* set header version */
  2469. X    writehdr(hdr,new);               /* write out the header */
  2470. X    filecopy(f,new,hdr->size);           /* copy over the data */
  2471. X}
  2472. X
  2473. Xstatic expandlst(n)               /* expand an indirect reference */
  2474. Xint n;                       /* number of entry to expand */
  2475. X{
  2476. X    FILE *lf, *fopen();               /* list file, opener */
  2477. X    char *malloc(), *realloc();           /* memory managers */
  2478. X    char buf[100];               /* input buffer */
  2479. X    int x;                   /* index */
  2480. X    char *p = lst[n]+1;               /* filename pointer */
  2481. X
  2482. X    if(*p)                   /* use name if one was given */
  2483. X    {     makefnam(p,".CMD",buf);
  2484. X     upper(buf);
  2485. X     if(!(lf=fopen(buf,"r")))
  2486. X          abort("Cannot read list of files in %s",buf);
  2487. X    }
  2488. X    else lf = stdin;               /* else use standard input */
  2489. X
  2490. X    for(x=n+1; x<lnum; x++)           /* drop reference from the list */
  2491. X     lst[x-1] = lst[x];
  2492. X    lnum--;
  2493. X
  2494. X    while(fscanf(lf,"%99s",buf)>0)     /* read in the list */
  2495. X    {     if(!(lst=(char **) realloc(lst,(lnum+1)*sizeof(char *))))
  2496. X          abort("too many file references");
  2497. X
  2498. X     lst[lnum] = malloc(strlen(buf)+1);
  2499. X     strcpy(lst[lnum],buf);           /* save the name */
  2500. X     lnum++;
  2501. X    }
  2502. X
  2503. X    if(lf!=stdin)               /* avoid closing standard input */
  2504. X     fclose(lf);
  2505. X}
  2506. ________This_Is_The_END________
  2507. if test `wc -c < marc.c` -ne     9053; then
  2508.     echo 'shar: marc.c was damaged during transit (should have been     9053 bytes)'
  2509. fi
  2510. fi        ; : end of overwriting check
  2511. exit 0
  2512.  
  2513. -- 
  2514. Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.
  2515.  
  2516.  
  2517.